diff --git a/contrib/completions/bash/kubectl b/contrib/completions/bash/kubectl index 33c0c4d911e..a70b466d59c 100644 --- a/contrib/completions/bash/kubectl +++ b/contrib/completions/bash/kubectl @@ -630,6 +630,7 @@ _kubectl_run() flags_completion=() flags+=("--attach") + flags+=("--command") flags+=("--dry-run") flags+=("--generator=") flags+=("--help") diff --git a/docs/man/man1/kubectl-run.1 b/docs/man/man1/kubectl-run.1 index 35fb89b3c5b..eec61448c75 100644 --- a/docs/man/man1/kubectl-run.1 +++ b/docs/man/man1/kubectl-run.1 @@ -22,6 +22,10 @@ Creates a replication controller to manage the created container(s). \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. +.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 \fB\-\-dry\-run\fP=false 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. $ 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 \-\- ... + +# Start the nginx container using a different command and custom arguments +$ kubectl run nginx \-\-image=nginx \-\-command \-\- ... + .fi .RE diff --git a/docs/user-guide/kubectl/kubectl_run.md b/docs/user-guide/kubectl/kubectl_run.md index 4f91cb01509..796c0496d57 100644 --- a/docs/user-guide/kubectl/kubectl_run.md +++ b/docs/user-guide/kubectl/kubectl_run.md @@ -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. $ 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 -- ... + +# Start the nginx container using a different command and custom arguments +$ kubectl run nginx --image=nginx --command -- ... ``` ### 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. + --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. --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 @@ -117,7 +127,7 @@ $ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { . * [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 [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_run.md?pixel)]() diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index b8ba4db6b0a..46f9fa784dd 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -127,8 +127,8 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) params["default-name"] = info.Name - if s, found := params["selector"]; !found || len(s) == 0 || cmdutil.GetFlagInt(cmd, "port") < 1 { - if len(s) == 0 { + if s, found := params["selector"]; !found || kubectl.IsZero(s) || cmdutil.GetFlagInt(cmd, "port") < 1 { + if kubectl.IsZero(s) { s, err := f.PodSelectorForObject(inputObject) if err != nil { 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") { params["create-external-load-balancer"] = "true" } - if len(params["labels"]) == 0 { + if kubectl.IsZero(params["labels"]) { labels, err := f.LabelsForObject(inputObject) if err != nil { return err diff --git a/pkg/kubectl/cmd/expose_test.go b/pkg/kubectl/cmd/expose_test.go index c92198aaeb7..2167b82cd24 100644 --- a/pkg/kubectl/cmd/expose_test.go +++ b/pkg/kubectl/cmd/expose_test.go @@ -30,16 +30,50 @@ import ( func TestRunExposeService(t *testing.T) { tests := []struct { - name string - args []string - ns string - calls map[string]string - input runtime.Object - flags map[string]string - output runtime.Object - expected string - status int + name string + args []string + ns string + calls map[string]string + input runtime.Object + flags map[string]string + output runtime.Object + expected string + 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", args: []string{"service", "baz"}, @@ -194,6 +228,8 @@ func TestRunExposeService(t *testing.T) { }), } tf.Namespace = test.ns + f.PodSelectorForObject = func(obj runtime.Object) (string, error) { return test.podSelector, nil } + buf := bytes.NewBuffer([]byte{}) cmd := NewCmdExposeService(f, buf) diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index bf8336a4092..724842de7b0 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -44,7 +44,16 @@ $ kubectl run nginx --image=nginx --replicas=5 $ 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. -$ 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 -- ... + +# Start the nginx container using a different command and custom arguments +$ kubectl run nginx --image=nginx --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("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().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 } @@ -82,7 +92,7 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob printDeprecationWarning("run", "run-container") } - if len(args) != 1 { + if len(args) == 0 { 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() params := kubectl.MakeParams(cmd, names) params["name"] = args[0] - + if len(args) > 1 { + params["args"] = args[1:] + } err = kubectl.ValidateParams(names, params) if err != nil { return err diff --git a/pkg/kubectl/generate.go b/pkg/kubectl/generate.go index c360f2ec4dd..a7a9168c4c6 100644 --- a/pkg/kubectl/generate.go +++ b/pkg/kubectl/generate.go @@ -18,6 +18,7 @@ package kubectl import ( "fmt" + "reflect" "strconv" "strings" @@ -35,17 +36,24 @@ type GeneratorParam struct { // Generator is an interface for things that can generate API objects from input parameters. type Generator interface { // 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() []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 -func ValidateParams(paramSpec []GeneratorParam, params map[string]string) error { +func ValidateParams(paramSpec []GeneratorParam, params map[string]interface{}) error { for ix := range paramSpec { if paramSpec[ix].Required { 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) } } @@ -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 -func MakeParams(cmd *cobra.Command, params []GeneratorParam) map[string]string { - result := map[string]string{} +func MakeParams(cmd *cobra.Command, params []GeneratorParam) map[string]interface{} { + result := map[string]interface{}{} for ix := range params { f := cmd.Flags().Lookup(params[ix].Name) 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 -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 { return nil, fmt.Errorf("no label spec passed") } diff --git a/pkg/kubectl/generate_test.go b/pkg/kubectl/generate_test.go index 952811c61ce..62823f9dc0d 100644 --- a/pkg/kubectl/generate_test.go +++ b/pkg/kubectl/generate_test.go @@ -23,29 +23,55 @@ import ( "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) { tests := []struct { paramSpec []GeneratorParam - params map[string]string + params map[string]interface{} valid bool }{ { paramSpec: []GeneratorParam{}, - params: map[string]string{}, + params: map[string]interface{}{}, valid: true, }, { paramSpec: []GeneratorParam{ {Name: "foo"}, }, - params: map[string]string{}, + params: map[string]interface{}{}, valid: true, }, { paramSpec: []GeneratorParam{ {Name: "foo", Required: true}, }, - params: map[string]string{ + params: map[string]interface{}{ "foo": "bar", }, valid: true, @@ -54,7 +80,7 @@ func TestValidateParams(t *testing.T) { paramSpec: []GeneratorParam{ {Name: "foo", Required: true}, }, - params: map[string]string{ + params: map[string]interface{}{ "baz": "blah", "foo": "bar", }, @@ -65,7 +91,7 @@ func TestValidateParams(t *testing.T) { {Name: "foo", Required: true}, {Name: "baz", Required: true}, }, - params: map[string]string{ + params: map[string]interface{}{ "baz": "blah", "foo": "bar", }, @@ -76,7 +102,7 @@ func TestValidateParams(t *testing.T) { {Name: "foo", Required: true}, {Name: "baz", Required: true}, }, - params: map[string]string{ + params: map[string]interface{}{ "foo": "bar", }, valid: false, @@ -103,7 +129,7 @@ func TestMakeParams(t *testing.T) { {Name: "foo", Required: true}, {Name: "baz", Required: true}, } - expected := map[string]string{ + expected := map[string]interface{}{ "foo": "bar", "baz": "blah", } diff --git a/pkg/kubectl/run.go b/pkg/kubectl/run.go index 5283c0d090a..6c2c5dd7a44 100644 --- a/pkg/kubectl/run.go +++ b/pkg/kubectl/run.go @@ -37,6 +37,8 @@ func (BasicReplicationController) ParamNames() []GeneratorParam { {"hostport", false}, {"stdin", 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 } -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"] if !found || len(name) == 0 { name, found = params["default-name"] @@ -95,6 +115,18 @@ func (BasicReplicationController) Generate(params map[string]string) (runtime.Ob if err != nil { 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{ ObjectMeta: api.ObjectMeta{ Name: name, @@ -164,10 +196,30 @@ func (BasicPod) ParamNames() []GeneratorParam { {"stdin", false}, {"tty", 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"] if !found || len(name) == 0 { name, found = params["default-name"] @@ -218,6 +270,17 @@ func (BasicPod) Generate(params map[string]string) (runtime.Object, error) { 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 { return nil, err } diff --git a/pkg/kubectl/run_test.go b/pkg/kubectl/run_test.go index 65ca8f32be3..66138f25f77 100644 --- a/pkg/kubectl/run_test.go +++ b/pkg/kubectl/run_test.go @@ -25,12 +25,12 @@ import ( func TestGenerate(t *testing.T) { tests := []struct { - params map[string]string + params map[string]interface{} expected *api.ReplicationController expectErr bool }{ { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "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", "image": "someimage", "replicas": "1", @@ -97,7 +164,7 @@ func TestGenerate(t *testing.T) { }, }, { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "replicas": "1", @@ -135,7 +202,7 @@ func TestGenerate(t *testing.T) { }, }, { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "replicas": "1", @@ -145,7 +212,7 @@ func TestGenerate(t *testing.T) { expectErr: true, }, { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "replicas": "1", @@ -193,12 +260,12 @@ func TestGenerate(t *testing.T) { func TestGeneratePod(t *testing.T) { tests := []struct { - params map[string]string + params map[string]interface{} expected *api.Pod expectErr bool }{ { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "port": "-1", @@ -221,7 +288,7 @@ func TestGeneratePod(t *testing.T) { }, }, { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "port": "80", @@ -249,7 +316,7 @@ func TestGeneratePod(t *testing.T) { }, }, { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "port": "80", @@ -279,7 +346,7 @@ func TestGeneratePod(t *testing.T) { }, }, { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "hostport": "80", @@ -288,7 +355,7 @@ func TestGeneratePod(t *testing.T) { expectErr: true, }, { - params: map[string]string{ + params: map[string]interface{}{ "name": "foo", "image": "someimage", "replicas": "1", diff --git a/pkg/kubectl/service.go b/pkg/kubectl/service.go index 78266d06b8f..cbf03a0427c 100644 --- a/pkg/kubectl/service.go +++ b/pkg/kubectl/service.go @@ -32,7 +32,7 @@ func (ServiceGeneratorV1) ParamNames() []GeneratorParam { 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" return generate(params) } @@ -43,7 +43,7 @@ func (ServiceGeneratorV2) ParamNames() []GeneratorParam { 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) } @@ -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"] if !found || len(selectorString) == 0 { return nil, fmt.Errorf("'selector' is a required parameter.") diff --git a/pkg/kubectl/service_test.go b/pkg/kubectl/service_test.go index 347ec787c59..6d8208014d1 100644 --- a/pkg/kubectl/service_test.go +++ b/pkg/kubectl/service_test.go @@ -27,12 +27,12 @@ import ( func TestGenerateService(t *testing.T) { tests := []struct { generator Generator - params map[string]string + params map[string]interface{} expected api.Service }{ { generator: ServiceGeneratorV2{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", @@ -61,7 +61,7 @@ func TestGenerateService(t *testing.T) { { generator: ServiceGeneratorV2{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", @@ -89,7 +89,7 @@ func TestGenerateService(t *testing.T) { }, { generator: ServiceGeneratorV2{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "labels": "key1=value1,key2=value2", "name": "test", @@ -122,7 +122,7 @@ func TestGenerateService(t *testing.T) { }, { generator: ServiceGeneratorV2{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", @@ -152,7 +152,7 @@ func TestGenerateService(t *testing.T) { }, { generator: ServiceGeneratorV2{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", @@ -184,7 +184,7 @@ func TestGenerateService(t *testing.T) { }, { generator: ServiceGeneratorV2{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", @@ -214,7 +214,7 @@ func TestGenerateService(t *testing.T) { }, { generator: ServiceGeneratorV2{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", @@ -245,7 +245,7 @@ func TestGenerateService(t *testing.T) { }, { generator: ServiceGeneratorV1{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80", @@ -274,7 +274,7 @@ func TestGenerateService(t *testing.T) { }, { generator: ServiceGeneratorV1{}, - params: map[string]string{ + params: map[string]interface{}{ "selector": "foo=bar,baz=blah", "name": "test", "port": "80",