From ffa764d60bd4e7768401a25e95eb77a0d7c9ddc0 Mon Sep 17 00:00:00 2001 From: Kris Rousey Date: Fri, 26 Jun 2015 13:49:34 -0700 Subject: [PATCH] Unify command line namespace resolution This change allows the namespace in kubeconfig to be overridden by specifying the namespace in the spec file. If namespace is explicitly provided in the command line flags and the spec file has a different namespace, this will cause an error. --- pkg/client/clientcmd/client_config.go | 19 ++++--- pkg/client/clientcmd/client_config_test.go | 19 ++++++- pkg/client/clientcmd/merged_client_builder.go | 4 +- pkg/kubectl/cmd/clusterinfo.go | 2 +- pkg/kubectl/cmd/cmd_test.go | 8 +-- pkg/kubectl/cmd/create.go | 6 +-- pkg/kubectl/cmd/delete.go | 4 +- pkg/kubectl/cmd/describe.go | 2 +- pkg/kubectl/cmd/exec.go | 2 +- pkg/kubectl/cmd/expose.go | 2 +- pkg/kubectl/cmd/get.go | 2 +- pkg/kubectl/cmd/label.go | 2 +- pkg/kubectl/cmd/log.go | 2 +- pkg/kubectl/cmd/patch.go | 2 +- pkg/kubectl/cmd/portforward.go | 2 +- pkg/kubectl/cmd/replace.go | 14 +++--- pkg/kubectl/cmd/rollingupdate.go | 7 +-- pkg/kubectl/cmd/run.go | 2 +- pkg/kubectl/cmd/scale.go | 2 +- pkg/kubectl/cmd/stop.go | 6 +-- pkg/kubectl/cmd/util/factory.go | 8 +-- pkg/kubectl/resource/builder.go | 10 +++- pkg/kubectl/resource/builder_test.go | 50 +++++++++++++++---- 23 files changed, 120 insertions(+), 57 deletions(-) diff --git a/pkg/client/clientcmd/client_config.go b/pkg/client/clientcmd/client_config.go index 65033636970..5245b3dc913 100644 --- a/pkg/client/clientcmd/client_config.go +++ b/pkg/client/clientcmd/client_config.go @@ -47,8 +47,10 @@ type ClientConfig interface { RawConfig() (clientcmdapi.Config, error) // ClientConfig returns a complete client config ClientConfig() (*client.Config, error) - // Namespace returns the namespace resulting from the merged result of all overrides - Namespace() (string, error) + // Namespace returns the namespace resulting from the merged + // result of all overrides and a boolean indicating if it was + // overridden + Namespace() (string, bool, error) } // DirectClientConfig is a ClientConfig interface that is backed by a clientcmdapi.Config, options overrides, and an optional fallbackReader for auth information @@ -207,17 +209,22 @@ func canIdentifyUser(config client.Config) bool { } // Namespace implements KubeConfig -func (config DirectClientConfig) Namespace() (string, error) { +func (config DirectClientConfig) Namespace() (string, bool, error) { if err := config.ConfirmUsable(); err != nil { - return "", err + return "", false, err } configContext := config.getContext() if len(configContext.Namespace) == 0 { - return api.NamespaceDefault, nil + return api.NamespaceDefault, false, nil } - return configContext.Namespace, nil + + overridden := false + if config.overrides != nil && config.overrides.Context.Namespace != "" { + overridden = true + } + return configContext.Namespace, overridden, nil } // ConfirmUsable looks a particular context and determines if that particular part of the config is useable. There might still be errors in the config, diff --git a/pkg/client/clientcmd/client_config_test.go b/pkg/client/clientcmd/client_config_test.go index 786c8b51b7d..4598003aed3 100644 --- a/pkg/client/clientcmd/client_config_test.go +++ b/pkg/client/clientcmd/client_config_test.go @@ -52,17 +52,32 @@ func TestMergeContext(t *testing.T) { const namespace = "overriden-namespace" config := createValidTestConfig() - clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{ + clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}) + + _, overridden, err := clientBuilder.Namespace() + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + if overridden { + t.Error("Expected namespace to not be overridden") + } + + clientBuilder = NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{ Context: clientcmdapi.Context{ Namespace: namespace, }, }) - actual, err := clientBuilder.Namespace() + actual, overridden, err := clientBuilder.Namespace() if err != nil { t.Errorf("Unexpected error: %v", err) } + if !overridden { + t.Error("Expected namespace to be overridden") + } + matchStringArg(namespace, actual, t) } diff --git a/pkg/client/clientcmd/merged_client_builder.go b/pkg/client/clientcmd/merged_client_builder.go index 36eafecf08e..996a5756134 100644 --- a/pkg/client/clientcmd/merged_client_builder.go +++ b/pkg/client/clientcmd/merged_client_builder.go @@ -94,10 +94,10 @@ func (config DeferredLoadingClientConfig) ClientConfig() (*client.Config, error) } // Namespace implements KubeConfig -func (config DeferredLoadingClientConfig) Namespace() (string, error) { +func (config DeferredLoadingClientConfig) Namespace() (string, bool, error) { mergedKubeConfig, err := config.createClientConfig() if err != nil { - return "", err + return "", false, err } return mergedKubeConfig.Namespace() diff --git a/pkg/kubectl/cmd/clusterinfo.go b/pkg/kubectl/cmd/clusterinfo.go index 9f78e5aca62..60d050882f3 100644 --- a/pkg/kubectl/cmd/clusterinfo.go +++ b/pkg/kubectl/cmd/clusterinfo.go @@ -57,7 +57,7 @@ func RunClusterInfo(factory *cmdutil.Factory, out io.Writer, cmd *cobra.Command) printService(out, "Kubernetes master", client.Host) mapper, typer := factory.Object() - cmdNamespace, err := factory.DefaultNamespace() + cmdNamespace, _, err := factory.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index 7991a57b776..94f2a53b979 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -146,8 +146,8 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { Validator: func() (validation.Schema, error) { return t.Validator, t.Err }, - DefaultNamespace: func() (string, error) { - return t.Namespace, t.Err + DefaultNamespace: func() (string, bool, error) { + return t.Namespace, false, t.Err }, ClientConfig: func() (*client.Config, error) { return t.ClientConfig, t.Err @@ -200,8 +200,8 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { Validator: func() (validation.Schema, error) { return t.Validator, t.Err }, - DefaultNamespace: func() (string, error) { - return t.Namespace, t.Err + DefaultNamespace: func() (string, bool, error) { + return t.Namespace, false, t.Err }, ClientConfig: func() (*client.Config, error) { return t.ClientConfig, t.Err diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 9ab9e4d83fe..199b07cd74d 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -75,7 +75,7 @@ func RunCreate(f *cmdutil.Factory, out io.Writer, filenames util.StringList) err return err } - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } @@ -84,8 +84,8 @@ func RunCreate(f *cmdutil.Factory, out io.Writer, filenames util.StringList) err r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). ContinueOnError(). - NamespaceParam(cmdNamespace).RequireNamespace(). - FilenameParam(filenames...). + NamespaceParam(cmdNamespace).DefaultNamespace(). + FilenameParam(enforceNamespace, filenames...). Flatten(). Do() err = r.Err() diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 0ee85c86c51..a8066e83c41 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -82,7 +82,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command { } func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error { - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } @@ -90,7 +90,7 @@ func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(filenames...). + FilenameParam(enforceNamespace, filenames...). SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). ResourceTypeOrNameArgs(false, args...).RequireObject(false). diff --git a/pkg/kubectl/cmd/describe.go b/pkg/kubectl/cmd/describe.go index 5b240636fe4..501b6c5be87 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -59,7 +59,7 @@ $ kubectl describe po -l name=myLabel`, func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { selector := cmdutil.GetFlagString(cmd, "selector") - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/exec.go b/pkg/kubectl/cmd/exec.go index 9709661828b..ab7dd3f5615 100644 --- a/pkg/kubectl/cmd/exec.go +++ b/pkg/kubectl/cmd/exec.go @@ -104,7 +104,7 @@ func extractPodAndContainer(cmd *cobra.Command, argsIn []string, p *execParams) func RunExec(f *cmdutil.Factory, cmd *cobra.Command, cmdIn io.Reader, cmdOut, cmdErr io.Writer, p *execParams, argsIn []string, re remoteExecutor) error { podName, containerName, args, err := extractPodAndContainer(cmd, argsIn, p) - namespace, err := f.DefaultNamespace() + namespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 09ceb587770..3ac5680a76c 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -74,7 +74,7 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command { } func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { - namespace, err := f.DefaultNamespace() + namespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 8cd8f506aaa..d913906807c 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -92,7 +92,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") mapper, typer := f.Object() - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index a35abcc923f..ef943393fa2 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -180,7 +180,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri overwrite := cmdutil.GetFlagBool(cmd, "overwrite") resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/log.go b/pkg/kubectl/cmd/log.go index 281f44c44fe..4f2660dec7e 100644 --- a/pkg/kubectl/cmd/log.go +++ b/pkg/kubectl/cmd/log.go @@ -94,7 +94,7 @@ func RunLog(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string return cmdutil.UsageError(cmd, "log POD [CONTAINER]") } - namespace, err := f.DefaultNamespace() + namespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index 3fd08e6b794..74b9bab2ce7 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -53,7 +53,7 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { } func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/portforward.go b/pkg/kubectl/cmd/portforward.go index 0547049831a..534c4d25319 100644 --- a/pkg/kubectl/cmd/portforward.go +++ b/pkg/kubectl/cmd/portforward.go @@ -83,7 +83,7 @@ func RunPortForward(f *cmdutil.Factory, cmd *cobra.Command, args []string, fw po return cmdutil.UsageError(cmd, "at least 1 PORT is required for port-forward") } - namespace, err := f.DefaultNamespace() + namespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/replace.go b/pkg/kubectl/cmd/replace.go index d8489ac4c8d..6efc88ec47f 100644 --- a/pkg/kubectl/cmd/replace.go +++ b/pkg/kubectl/cmd/replace.go @@ -77,7 +77,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st return err } - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } @@ -95,8 +95,8 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). ContinueOnError(). - NamespaceParam(cmdNamespace).RequireNamespace(). - FilenameParam(filenames...). + NamespaceParam(cmdNamespace).DefaultNamespace(). + FilenameParam(enforceNamespace, filenames...). Flatten(). Do() err = r.Err() @@ -126,7 +126,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] return err } - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } @@ -135,7 +135,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(filenames...). + FilenameParam(enforceNamespace, filenames...). ResourceTypeOrNameArgs(false, args...).RequireObject(false). Flatten(). Do() @@ -159,8 +159,8 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] r = resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). ContinueOnError(). - NamespaceParam(cmdNamespace).RequireNamespace(). - FilenameParam(filenames...). + NamespaceParam(cmdNamespace).DefaultNamespace(). + FilenameParam(enforceNamespace, filenames...). Flatten(). Do() err = r.Err() diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 3d034db0575..5ef7193693a 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -117,7 +117,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg timeout := cmdutil.GetFlagDuration(cmd, "timeout") dryrun := cmdutil.GetFlagBool(cmd, "dry-run") - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } @@ -154,10 +154,11 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg if err != nil { return err } + request := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). - NamespaceParam(cmdNamespace).RequireNamespace(). - FilenameParam(filename). + NamespaceParam(cmdNamespace).DefaultNamespace(). + FilenameParam(enforceNamespace, filename). Do() obj, err := request.Object() if err != nil { diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 014db501298..9a0cb505f51 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -78,7 +78,7 @@ func Run(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) e return cmdutil.UsageError(cmd, "NAME is required for run") } - namespace, err := f.DefaultNamespace() + namespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/scale.go b/pkg/kubectl/cmd/scale.go index 95c3aa837ed..7ae34677d27 100644 --- a/pkg/kubectl/cmd/scale.go +++ b/pkg/kubectl/cmd/scale.go @@ -74,7 +74,7 @@ func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri return cmdutil.UsageError(cmd, "--replicas=COUNT RESOURCE ID") } - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } diff --git a/pkg/kubectl/cmd/stop.go b/pkg/kubectl/cmd/stop.go index ac8b443cf40..96b59fbe782 100644 --- a/pkg/kubectl/cmd/stop.go +++ b/pkg/kubectl/cmd/stop.go @@ -68,16 +68,16 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command { } func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, filenames util.StringList, out io.Writer) error { - cmdNamespace, err := f.DefaultNamespace() + cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). - NamespaceParam(cmdNamespace).RequireNamespace(). + NamespaceParam(cmdNamespace).DefaultNamespace(). ResourceTypeOrNameArgs(false, args...). - FilenameParam(filenames...). + FilenameParam(enforceNamespace, filenames...). SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). Flatten(). diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 34493380c3b..94d436adb40 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -78,8 +78,10 @@ type Factory struct { LabelsForObject func(object runtime.Object) (map[string]string, error) // Returns a schema that can validate objects stored on disk. Validator func() (validation.Schema, error) - // Returns the default namespace to use in cases where no other namespace is specified - DefaultNamespace func() (string, error) + // Returns the default namespace to use in cases where no + // other namespace is specified and whether the namespace was + // overriden. + DefaultNamespace func() (string, bool, error) // Returns the generator for the provided generator name Generator func(name string) (kubectl.Generator, bool) } @@ -209,7 +211,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { } return validation.NullSchema{}, nil }, - DefaultNamespace: func() (string, error) { + DefaultNamespace: func() (string, bool, error) { return clientConfig.Namespace() }, Generator: func(name string) (kubectl.Generator, bool) { diff --git a/pkg/kubectl/resource/builder.go b/pkg/kubectl/resource/builder.go index 045b2d89f05..9895ed1494e 100644 --- a/pkg/kubectl/resource/builder.go +++ b/pkg/kubectl/resource/builder.go @@ -87,9 +87,12 @@ func (b *Builder) Schema(schema validation.Schema) *Builder { } // FilenameParam groups input in two categories: URLs and files (files, directories, STDIN) +// If enforceNamespace is false, namespaces in the specs will be allowed to +// override the default namespace. If it is true, namespaces that don't match +// will cause an error. // If ContinueOnError() is set prior to this method, objects on the path that are not // recognized will be ignored (but logged at V(2)). -func (b *Builder) FilenameParam(paths ...string) *Builder { +func (b *Builder) FilenameParam(enforceNamespace bool, paths ...string) *Builder { for _, s := range paths { switch { case s == "-": @@ -105,6 +108,11 @@ func (b *Builder) FilenameParam(paths ...string) *Builder { b.Path(s) } } + + if enforceNamespace { + b.RequireNamespace() + } + return b } diff --git a/pkg/kubectl/resource/builder_test.go b/pkg/kubectl/resource/builder_test.go index d900322a168..df05bf9afd7 100644 --- a/pkg/kubectl/resource/builder_test.go +++ b/pkg/kubectl/resource/builder_test.go @@ -177,7 +177,7 @@ func (v *testVisitor) Objects() []runtime.Object { func TestPathBuilder(t *testing.T) { b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). - FilenameParam("../../../examples/guestbook/redis-master-controller.yaml") + FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml") test := &testVisitor{} singular := false @@ -227,8 +227,8 @@ func TestNodeBuilder(t *testing.T) { func TestPathBuilderWithMultiple(t *testing.T) { b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). - FilenameParam("../../../examples/guestbook/redis-master-controller.yaml"). - FilenameParam("../../../examples/guestbook/redis-master-controller.yaml"). + FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml"). + FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml"). NamespaceParam("test").DefaultNamespace() test := &testVisitor{} @@ -247,7 +247,7 @@ func TestPathBuilderWithMultiple(t *testing.T) { func TestDirectoryBuilder(t *testing.T) { b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). - FilenameParam("../../../examples/guestbook"). + FilenameParam(false, "../../../examples/guestbook"). NamespaceParam("test").DefaultNamespace() test := &testVisitor{} @@ -269,6 +269,36 @@ func TestDirectoryBuilder(t *testing.T) { } } +func TestNamespaceOverride(t *testing.T) { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) + })) + defer s.Close() + + b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + FilenameParam(false, s.URL). + NamespaceParam("test") + + test := &testVisitor{} + + err := b.Do().Visit(test.Handle) + if err != nil || len(test.Infos) != 1 && test.Infos[0].Namespace != "foo" { + t.Fatalf("unexpected response: %v %#v", err, test.Infos) + } + + b = NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + FilenameParam(true, s.URL). + NamespaceParam("test") + + test = &testVisitor{} + + err = b.Do().Visit(test.Handle) + if err == nil { + t.Fatalf("expected namespace error. got: %#v", test.Infos) + } +} + func TestURLBuilder(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) @@ -277,7 +307,7 @@ func TestURLBuilder(t *testing.T) { defer s.Close() b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). - FilenameParam(s.URL). + FilenameParam(false, s.URL). NamespaceParam("test") test := &testVisitor{} @@ -301,7 +331,7 @@ func TestURLBuilderRequireNamespace(t *testing.T) { defer s.Close() b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). - FilenameParam(s.URL). + FilenameParam(false, s.URL). NamespaceParam("test").RequireNamespace() test := &testVisitor{} @@ -640,7 +670,7 @@ func TestContinueOnErrorVisitor(t *testing.T) { func TestSingularObject(t *testing.T) { obj, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). NamespaceParam("test").DefaultNamespace(). - FilenameParam("../../../examples/guestbook/redis-master-controller.yaml"). + FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml"). Flatten(). Do().Object() @@ -751,7 +781,7 @@ func TestWatch(t *testing.T) { }), })). NamespaceParam("test").DefaultNamespace(). - FilenameParam("../../../examples/guestbook/redis-master-service.yaml").Flatten(). + FilenameParam(false, "../../../examples/guestbook/redis-master-service.yaml").Flatten(). Do().Watch("12") if err != nil { @@ -778,8 +808,8 @@ func TestWatch(t *testing.T) { func TestWatchMultipleError(t *testing.T) { _, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). NamespaceParam("test").DefaultNamespace(). - FilenameParam("../../../examples/guestbook/redis-master-controller.yaml").Flatten(). - FilenameParam("../../../examples/guestbook/redis-master-controller.yaml").Flatten(). + FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").Flatten(). + FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").Flatten(). Do().Watch("") if err == nil {