Commit ffa764d6 authored by Kris Rousey's avatar Kris Rousey

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.
parent 588bc9be
...@@ -47,8 +47,10 @@ type ClientConfig interface { ...@@ -47,8 +47,10 @@ type ClientConfig interface {
RawConfig() (clientcmdapi.Config, error) RawConfig() (clientcmdapi.Config, error)
// ClientConfig returns a complete client config // ClientConfig returns a complete client config
ClientConfig() (*client.Config, error) ClientConfig() (*client.Config, error)
// Namespace returns the namespace resulting from the merged result of all overrides // Namespace returns the namespace resulting from the merged
Namespace() (string, error) // 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 // 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 { ...@@ -207,17 +209,22 @@ func canIdentifyUser(config client.Config) bool {
} }
// Namespace implements KubeConfig // Namespace implements KubeConfig
func (config DirectClientConfig) Namespace() (string, error) { func (config DirectClientConfig) Namespace() (string, bool, error) {
if err := config.ConfirmUsable(); err != nil { if err := config.ConfirmUsable(); err != nil {
return "", err return "", false, err
} }
configContext := config.getContext() configContext := config.getContext()
if len(configContext.Namespace) == 0 { 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, // ConfirmUsable looks a particular context and determines if that particular part of the config is useable. There might still be errors in the config,
......
...@@ -52,17 +52,32 @@ func TestMergeContext(t *testing.T) { ...@@ -52,17 +52,32 @@ func TestMergeContext(t *testing.T) {
const namespace = "overriden-namespace" const namespace = "overriden-namespace"
config := createValidTestConfig() 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{ Context: clientcmdapi.Context{
Namespace: namespace, Namespace: namespace,
}, },
}) })
actual, err := clientBuilder.Namespace() actual, overridden, err := clientBuilder.Namespace()
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
if !overridden {
t.Error("Expected namespace to be overridden")
}
matchStringArg(namespace, actual, t) matchStringArg(namespace, actual, t)
} }
......
...@@ -94,10 +94,10 @@ func (config DeferredLoadingClientConfig) ClientConfig() (*client.Config, error) ...@@ -94,10 +94,10 @@ func (config DeferredLoadingClientConfig) ClientConfig() (*client.Config, error)
} }
// Namespace implements KubeConfig // Namespace implements KubeConfig
func (config DeferredLoadingClientConfig) Namespace() (string, error) { func (config DeferredLoadingClientConfig) Namespace() (string, bool, error) {
mergedKubeConfig, err := config.createClientConfig() mergedKubeConfig, err := config.createClientConfig()
if err != nil { if err != nil {
return "", err return "", false, err
} }
return mergedKubeConfig.Namespace() return mergedKubeConfig.Namespace()
......
...@@ -57,7 +57,7 @@ func RunClusterInfo(factory *cmdutil.Factory, out io.Writer, cmd *cobra.Command) ...@@ -57,7 +57,7 @@ func RunClusterInfo(factory *cmdutil.Factory, out io.Writer, cmd *cobra.Command)
printService(out, "Kubernetes master", client.Host) printService(out, "Kubernetes master", client.Host)
mapper, typer := factory.Object() mapper, typer := factory.Object()
cmdNamespace, err := factory.DefaultNamespace() cmdNamespace, _, err := factory.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -146,8 +146,8 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { ...@@ -146,8 +146,8 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
Validator: func() (validation.Schema, error) { Validator: func() (validation.Schema, error) {
return t.Validator, t.Err return t.Validator, t.Err
}, },
DefaultNamespace: func() (string, error) { DefaultNamespace: func() (string, bool, error) {
return t.Namespace, t.Err return t.Namespace, false, t.Err
}, },
ClientConfig: func() (*client.Config, error) { ClientConfig: func() (*client.Config, error) {
return t.ClientConfig, t.Err return t.ClientConfig, t.Err
...@@ -200,8 +200,8 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { ...@@ -200,8 +200,8 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
Validator: func() (validation.Schema, error) { Validator: func() (validation.Schema, error) {
return t.Validator, t.Err return t.Validator, t.Err
}, },
DefaultNamespace: func() (string, error) { DefaultNamespace: func() (string, bool, error) {
return t.Namespace, t.Err return t.Namespace, false, t.Err
}, },
ClientConfig: func() (*client.Config, error) { ClientConfig: func() (*client.Config, error) {
return t.ClientConfig, t.Err return t.ClientConfig, t.Err
......
...@@ -75,7 +75,7 @@ func RunCreate(f *cmdutil.Factory, out io.Writer, filenames util.StringList) err ...@@ -75,7 +75,7 @@ func RunCreate(f *cmdutil.Factory, out io.Writer, filenames util.StringList) err
return err return err
} }
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
...@@ -84,8 +84,8 @@ func RunCreate(f *cmdutil.Factory, out io.Writer, filenames util.StringList) err ...@@ -84,8 +84,8 @@ func RunCreate(f *cmdutil.Factory, out io.Writer, filenames util.StringList) err
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
Schema(schema). Schema(schema).
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).RequireNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(filenames...). FilenameParam(enforceNamespace, filenames...).
Flatten(). Flatten().
Do() Do()
err = r.Err() err = r.Err()
......
...@@ -82,7 +82,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -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 { 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 { if err != nil {
return err return err
} }
...@@ -90,7 +90,7 @@ func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str ...@@ -90,7 +90,7 @@ func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(filenames...). FilenameParam(enforceNamespace, filenames...).
SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). SelectAllParam(cmdutil.GetFlagBool(cmd, "all")).
ResourceTypeOrNameArgs(false, args...).RequireObject(false). ResourceTypeOrNameArgs(false, args...).RequireObject(false).
......
...@@ -59,7 +59,7 @@ $ kubectl describe po -l name=myLabel`, ...@@ -59,7 +59,7 @@ $ kubectl describe po -l name=myLabel`,
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
selector := cmdutil.GetFlagString(cmd, "selector") selector := cmdutil.GetFlagString(cmd, "selector")
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -104,7 +104,7 @@ func extractPodAndContainer(cmd *cobra.Command, argsIn []string, p *execParams) ...@@ -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 { 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) podName, containerName, args, err := extractPodAndContainer(cmd, argsIn, p)
namespace, err := f.DefaultNamespace() namespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -74,7 +74,7 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -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 { 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 { if err != nil {
return err return err
} }
......
...@@ -92,7 +92,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string ...@@ -92,7 +92,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces")
mapper, typer := f.Object() mapper, typer := f.Object()
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -180,7 +180,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri ...@@ -180,7 +180,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
overwrite := cmdutil.GetFlagBool(cmd, "overwrite") overwrite := cmdutil.GetFlagBool(cmd, "overwrite")
resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -94,7 +94,7 @@ func RunLog(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string ...@@ -94,7 +94,7 @@ func RunLog(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
return cmdutil.UsageError(cmd, "log POD [CONTAINER]") return cmdutil.UsageError(cmd, "log POD [CONTAINER]")
} }
namespace, err := f.DefaultNamespace() namespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -53,7 +53,7 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -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 { 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 { if err != nil {
return err return err
} }
......
...@@ -83,7 +83,7 @@ func RunPortForward(f *cmdutil.Factory, cmd *cobra.Command, args []string, fw po ...@@ -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") return cmdutil.UsageError(cmd, "at least 1 PORT is required for port-forward")
} }
namespace, err := f.DefaultNamespace() namespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -77,7 +77,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st ...@@ -77,7 +77,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
return err return err
} }
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
...@@ -95,8 +95,8 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st ...@@ -95,8 +95,8 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
Schema(schema). Schema(schema).
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).RequireNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(filenames...). FilenameParam(enforceNamespace, filenames...).
Flatten(). Flatten().
Do() Do()
err = r.Err() err = r.Err()
...@@ -126,7 +126,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] ...@@ -126,7 +126,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
return err return err
} }
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
...@@ -135,7 +135,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] ...@@ -135,7 +135,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(filenames...). FilenameParam(enforceNamespace, filenames...).
ResourceTypeOrNameArgs(false, args...).RequireObject(false). ResourceTypeOrNameArgs(false, args...).RequireObject(false).
Flatten(). Flatten().
Do() Do()
...@@ -159,8 +159,8 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] ...@@ -159,8 +159,8 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
r = resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). r = resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
Schema(schema). Schema(schema).
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).RequireNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(filenames...). FilenameParam(enforceNamespace, filenames...).
Flatten(). Flatten().
Do() Do()
err = r.Err() err = r.Err()
......
...@@ -117,7 +117,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg ...@@ -117,7 +117,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
timeout := cmdutil.GetFlagDuration(cmd, "timeout") timeout := cmdutil.GetFlagDuration(cmd, "timeout")
dryrun := cmdutil.GetFlagBool(cmd, "dry-run") dryrun := cmdutil.GetFlagBool(cmd, "dry-run")
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
...@@ -154,10 +154,11 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg ...@@ -154,10 +154,11 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
if err != nil { if err != nil {
return err return err
} }
request := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). request := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
Schema(schema). Schema(schema).
NamespaceParam(cmdNamespace).RequireNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(filename). FilenameParam(enforceNamespace, filename).
Do() Do()
obj, err := request.Object() obj, err := request.Object()
if err != nil { if err != nil {
......
...@@ -78,7 +78,7 @@ func Run(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) e ...@@ -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") return cmdutil.UsageError(cmd, "NAME is required for run")
} }
namespace, err := f.DefaultNamespace() namespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -74,7 +74,7 @@ func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri ...@@ -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") return cmdutil.UsageError(cmd, "--replicas=COUNT RESOURCE ID")
} }
cmdNamespace, err := f.DefaultNamespace() cmdNamespace, _, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -68,16 +68,16 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -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 { 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 { if err != nil {
return err return err
} }
mapper, typer := f.Object() mapper, typer := f.Object()
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).RequireNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
ResourceTypeOrNameArgs(false, args...). ResourceTypeOrNameArgs(false, args...).
FilenameParam(filenames...). FilenameParam(enforceNamespace, filenames...).
SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). SelectAllParam(cmdutil.GetFlagBool(cmd, "all")).
Flatten(). Flatten().
......
...@@ -78,8 +78,10 @@ type Factory struct { ...@@ -78,8 +78,10 @@ type Factory struct {
LabelsForObject func(object runtime.Object) (map[string]string, error) LabelsForObject func(object runtime.Object) (map[string]string, error)
// Returns a schema that can validate objects stored on disk. // Returns a schema that can validate objects stored on disk.
Validator func() (validation.Schema, error) Validator func() (validation.Schema, error)
// Returns the default namespace to use in cases where no other namespace is specified // Returns the default namespace to use in cases where no
DefaultNamespace func() (string, error) // other namespace is specified and whether the namespace was
// overriden.
DefaultNamespace func() (string, bool, error)
// Returns the generator for the provided generator name // Returns the generator for the provided generator name
Generator func(name string) (kubectl.Generator, bool) Generator func(name string) (kubectl.Generator, bool)
} }
...@@ -209,7 +211,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { ...@@ -209,7 +211,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
} }
return validation.NullSchema{}, nil return validation.NullSchema{}, nil
}, },
DefaultNamespace: func() (string, error) { DefaultNamespace: func() (string, bool, error) {
return clientConfig.Namespace() return clientConfig.Namespace()
}, },
Generator: func(name string) (kubectl.Generator, bool) { Generator: func(name string) (kubectl.Generator, bool) {
......
...@@ -87,9 +87,12 @@ func (b *Builder) Schema(schema validation.Schema) *Builder { ...@@ -87,9 +87,12 @@ func (b *Builder) Schema(schema validation.Schema) *Builder {
} }
// FilenameParam groups input in two categories: URLs and files (files, directories, STDIN) // 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 // If ContinueOnError() is set prior to this method, objects on the path that are not
// recognized will be ignored (but logged at V(2)). // 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 { for _, s := range paths {
switch { switch {
case s == "-": case s == "-":
...@@ -105,6 +108,11 @@ func (b *Builder) FilenameParam(paths ...string) *Builder { ...@@ -105,6 +108,11 @@ func (b *Builder) FilenameParam(paths ...string) *Builder {
b.Path(s) b.Path(s)
} }
} }
if enforceNamespace {
b.RequireNamespace()
}
return b return b
} }
......
...@@ -177,7 +177,7 @@ func (v *testVisitor) Objects() []runtime.Object { ...@@ -177,7 +177,7 @@ func (v *testVisitor) Objects() []runtime.Object {
func TestPathBuilder(t *testing.T) { func TestPathBuilder(t *testing.T) {
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()).
FilenameParam("../../../examples/guestbook/redis-master-controller.yaml") FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml")
test := &testVisitor{} test := &testVisitor{}
singular := false singular := false
...@@ -227,8 +227,8 @@ func TestNodeBuilder(t *testing.T) { ...@@ -227,8 +227,8 @@ func TestNodeBuilder(t *testing.T) {
func TestPathBuilderWithMultiple(t *testing.T) { func TestPathBuilderWithMultiple(t *testing.T) {
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()).
FilenameParam("../../../examples/guestbook/redis-master-controller.yaml"). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").
FilenameParam("../../../examples/guestbook/redis-master-controller.yaml"). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").
NamespaceParam("test").DefaultNamespace() NamespaceParam("test").DefaultNamespace()
test := &testVisitor{} test := &testVisitor{}
...@@ -247,7 +247,7 @@ func TestPathBuilderWithMultiple(t *testing.T) { ...@@ -247,7 +247,7 @@ func TestPathBuilderWithMultiple(t *testing.T) {
func TestDirectoryBuilder(t *testing.T) { func TestDirectoryBuilder(t *testing.T) {
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()).
FilenameParam("../../../examples/guestbook"). FilenameParam(false, "../../../examples/guestbook").
NamespaceParam("test").DefaultNamespace() NamespaceParam("test").DefaultNamespace()
test := &testVisitor{} test := &testVisitor{}
...@@ -269,6 +269,36 @@ func TestDirectoryBuilder(t *testing.T) { ...@@ -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) { func TestURLBuilder(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
...@@ -277,7 +307,7 @@ func TestURLBuilder(t *testing.T) { ...@@ -277,7 +307,7 @@ func TestURLBuilder(t *testing.T) {
defer s.Close() defer s.Close()
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()).
FilenameParam(s.URL). FilenameParam(false, s.URL).
NamespaceParam("test") NamespaceParam("test")
test := &testVisitor{} test := &testVisitor{}
...@@ -301,7 +331,7 @@ func TestURLBuilderRequireNamespace(t *testing.T) { ...@@ -301,7 +331,7 @@ func TestURLBuilderRequireNamespace(t *testing.T) {
defer s.Close() defer s.Close()
b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()).
FilenameParam(s.URL). FilenameParam(false, s.URL).
NamespaceParam("test").RequireNamespace() NamespaceParam("test").RequireNamespace()
test := &testVisitor{} test := &testVisitor{}
...@@ -640,7 +670,7 @@ func TestContinueOnErrorVisitor(t *testing.T) { ...@@ -640,7 +670,7 @@ func TestContinueOnErrorVisitor(t *testing.T) {
func TestSingularObject(t *testing.T) { func TestSingularObject(t *testing.T) {
obj, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). obj, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()).
NamespaceParam("test").DefaultNamespace(). NamespaceParam("test").DefaultNamespace().
FilenameParam("../../../examples/guestbook/redis-master-controller.yaml"). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").
Flatten(). Flatten().
Do().Object() Do().Object()
...@@ -751,7 +781,7 @@ func TestWatch(t *testing.T) { ...@@ -751,7 +781,7 @@ func TestWatch(t *testing.T) {
}), }),
})). })).
NamespaceParam("test").DefaultNamespace(). NamespaceParam("test").DefaultNamespace().
FilenameParam("../../../examples/guestbook/redis-master-service.yaml").Flatten(). FilenameParam(false, "../../../examples/guestbook/redis-master-service.yaml").Flatten().
Do().Watch("12") Do().Watch("12")
if err != nil { if err != nil {
...@@ -778,8 +808,8 @@ func TestWatch(t *testing.T) { ...@@ -778,8 +808,8 @@ func TestWatch(t *testing.T) {
func TestWatchMultipleError(t *testing.T) { func TestWatchMultipleError(t *testing.T) {
_, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). _, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()).
NamespaceParam("test").DefaultNamespace(). NamespaceParam("test").DefaultNamespace().
FilenameParam("../../../examples/guestbook/redis-master-controller.yaml").Flatten(). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").Flatten().
FilenameParam("../../../examples/guestbook/redis-master-controller.yaml").Flatten(). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").Flatten().
Do().Watch("") Do().Watch("")
if err == nil { if err == nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment