mirror of https://github.com/knative/client.git
Set current namespace from kubeconfig by default (#172)
* Set current namespace from kubeconfig by default Currently kn command does not pick up namespace from kubeconfig but hardcorded default namespace. This patch fixes to get namespace from kubeconfig. Fixes https://github.com/knative/client/issues/7 * Use NamespaceFactory to get current namespace * Update unit tests * Add nil check for ClientConfig
This commit is contained in:
parent
9c865a6115
commit
13ff277095
|
|
@ -21,10 +21,6 @@ import (
|
||||||
"github.com/knative/client/pkg/kn/core"
|
"github.com/knative/client/pkg/kn/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
core.InitializeConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := core.NewKnCommand().Execute()
|
err := core.NewKnCommand().Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,6 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: default namespace should be same scope for the request
|
|
||||||
const defaultNamespace = "default"
|
|
||||||
|
|
||||||
// AddNamespaceFlags adds the namespace-related flags:
|
// AddNamespaceFlags adds the namespace-related flags:
|
||||||
// * --namespace
|
// * --namespace
|
||||||
// * --all-namespaces
|
// * --all-namespaces
|
||||||
|
|
@ -43,7 +40,7 @@ func AddNamespaceFlags(flags *pflag.FlagSet, allowAll bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNamespace returns namespace from command specified by flag
|
// GetNamespace returns namespace from command specified by flag
|
||||||
func GetNamespace(cmd *cobra.Command) (string, error) {
|
func (kn *KnParams) GetNamespace(cmd *cobra.Command) (string, error) {
|
||||||
namespace := cmd.Flag("namespace").Value.String()
|
namespace := cmd.Flag("namespace").Value.String()
|
||||||
// check value of all-namepace only if its defined
|
// check value of all-namepace only if its defined
|
||||||
if cmd.Flags().Lookup("all-namespaces") != nil {
|
if cmd.Flags().Lookup("all-namespaces") != nil {
|
||||||
|
|
@ -57,7 +54,11 @@ func GetNamespace(cmd *cobra.Command) (string, error) {
|
||||||
}
|
}
|
||||||
// if all-namepaces=False or namespace not given, use default namespace
|
// if all-namepaces=False or namespace not given, use default namespace
|
||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
namespace = defaultNamespace
|
var err error
|
||||||
|
namespace, err = kn.NamespaceFactory()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return namespace, nil
|
return namespace, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ func TestGetNamespaceSample(t *testing.T) {
|
||||||
expectedNamespace := "test1"
|
expectedNamespace := "test1"
|
||||||
testCmd.SetArgs([]string{"--namespace", expectedNamespace})
|
testCmd.SetArgs([]string{"--namespace", expectedNamespace})
|
||||||
testCmd.Execute()
|
testCmd.Execute()
|
||||||
actualNamespace, err := GetNamespace(testCmd)
|
kp := &KnParams{NamespaceFactory: func() (string, error) { return FakeNamespace, nil }}
|
||||||
|
actualNamespace, err := kp.GetNamespace(testCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -45,12 +46,13 @@ func TestGetNamespaceSample(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test without setting any namespace
|
// test current namespace without setting any namespace
|
||||||
func TestGetNamespaceDefault(t *testing.T) {
|
func TestGetNamespaceDefault(t *testing.T) {
|
||||||
testCmd := testCommandGenerator(true)
|
testCmd := testCommandGenerator(true)
|
||||||
expectedNamespace := "default"
|
expectedNamespace := "current"
|
||||||
testCmd.Execute()
|
testCmd.Execute()
|
||||||
actualNamespace, err := GetNamespace(testCmd)
|
kp := &KnParams{NamespaceFactory: func() (string, error) { return FakeNamespace, nil }}
|
||||||
|
actualNamespace, err := kp.GetNamespace(testCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +69,8 @@ func TestGetNamespaceAllNamespacesSet(t *testing.T) {
|
||||||
sampleNamespace := "test1"
|
sampleNamespace := "test1"
|
||||||
testCmd.SetArgs([]string{"--namespace", sampleNamespace, "--all-namespaces"})
|
testCmd.SetArgs([]string{"--namespace", sampleNamespace, "--all-namespaces"})
|
||||||
testCmd.Execute()
|
testCmd.Execute()
|
||||||
actualNamespace, err := GetNamespace(testCmd)
|
kp := &KnParams{NamespaceFactory: func() (string, error) { return FakeNamespace, nil }}
|
||||||
|
actualNamespace, err := kp.GetNamespace(testCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +86,8 @@ func TestGetNamespaceDefaultAllNamespacesUnset(t *testing.T) {
|
||||||
expectedNamespace := ""
|
expectedNamespace := ""
|
||||||
testCmd.SetArgs([]string{"--all-namespaces"})
|
testCmd.SetArgs([]string{"--all-namespaces"})
|
||||||
testCmd.Execute()
|
testCmd.Execute()
|
||||||
actualNamespace, err := GetNamespace(testCmd)
|
kp := &KnParams{NamespaceFactory: func() (string, error) { return FakeNamespace, nil }}
|
||||||
|
actualNamespace, err := kp.GetNamespace(testCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -98,21 +102,8 @@ func TestGetNamespaceAllNamespacesNotDefined(t *testing.T) {
|
||||||
expectedNamespace := "test1"
|
expectedNamespace := "test1"
|
||||||
testCmd.SetArgs([]string{"--namespace", expectedNamespace})
|
testCmd.SetArgs([]string{"--namespace", expectedNamespace})
|
||||||
testCmd.Execute()
|
testCmd.Execute()
|
||||||
actualNamespace, err := GetNamespace(testCmd)
|
kp := &KnParams{NamespaceFactory: func() (string, error) { return FakeNamespace, nil }}
|
||||||
if err != nil {
|
actualNamespace, err := kp.GetNamespace(testCmd)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if actualNamespace != expectedNamespace {
|
|
||||||
t.Fatalf("Incorrect namespace retrieved: %v, expected: %v", actualNamespace, expectedNamespace)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// test with all-namespace flag not defined and no namespace given
|
|
||||||
func TestGetNamespaceDefaultAllNamespacesNotDefined(t *testing.T) {
|
|
||||||
testCmd := testCommandGenerator(false)
|
|
||||||
expectedNamespace := "default"
|
|
||||||
testCmd.Execute()
|
|
||||||
actualNamespace, err := GetNamespace(testCmd)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func NewRevisionDescribeCommand(p *commands.KnParams) *cobra.Command {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, err := commands.GetNamespace(cmd)
|
namespace, err := p.GetNamespace(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ func NewRevisionListCommand(p *commands.KnParams) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
namespace, err := commands.GetNamespace(cmd)
|
namespace, err := p.GetNamespace(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func NewServiceCreateCommand(p *commands.KnParams) *cobra.Command {
|
||||||
return errors.New("requires the image name to run.")
|
return errors.New("requires the image name to run.")
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, err := commands.GetNamespace(cmd)
|
namespace, err := p.GetNamespace(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ func TestServiceCreateImage(t *testing.T) {
|
||||||
} else if template.Spec.DeprecatedContainer.Image != "gcr.io/foo/bar:baz" {
|
} else if template.Spec.DeprecatedContainer.Image != "gcr.io/foo/bar:baz" {
|
||||||
t.Fatalf("wrong image set: %v", template.Spec.DeprecatedContainer.Image)
|
t.Fatalf("wrong image set: %v", template.Spec.DeprecatedContainer.Image)
|
||||||
} else if !strings.Contains(output, "foo") || !strings.Contains(output, "created") ||
|
} else if !strings.Contains(output, "foo") || !strings.Contains(output, "created") ||
|
||||||
!strings.Contains(output, "default") {
|
!strings.Contains(output, commands.FakeNamespace) {
|
||||||
t.Fatalf("wrong stdout message: %v", output)
|
t.Fatalf("wrong stdout message: %v", output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -338,7 +338,7 @@ func TestServiceCreateImageForce(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if template.Spec.DeprecatedContainer.Image != "gcr.io/foo/bar:v2" {
|
} else if template.Spec.DeprecatedContainer.Image != "gcr.io/foo/bar:v2" {
|
||||||
t.Fatalf("wrong image set: %v", template.Spec.DeprecatedContainer.Image)
|
t.Fatalf("wrong image set: %v", template.Spec.DeprecatedContainer.Image)
|
||||||
} else if !strings.Contains(output, "foo") || !strings.Contains(output, "default") {
|
} else if !strings.Contains(output, "foo") || !strings.Contains(output, commands.FakeNamespace) {
|
||||||
t.Fatalf("wrong output: %s", output)
|
t.Fatalf("wrong output: %s", output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -375,7 +375,7 @@ func TestServiceCreateEnvForce(t *testing.T) {
|
||||||
actualEnvVars,
|
actualEnvVars,
|
||||||
expectedEnvVars) {
|
expectedEnvVars) {
|
||||||
t.Fatalf("wrong env vars:%v", template.Spec.DeprecatedContainer.Env)
|
t.Fatalf("wrong env vars:%v", template.Spec.DeprecatedContainer.Env)
|
||||||
} else if !strings.Contains(output, "foo") || !strings.Contains(output, "default") {
|
} else if !strings.Contains(output, "foo") || !strings.Contains(output, commands.FakeNamespace) {
|
||||||
t.Fatalf("wrong output: %s", output)
|
t.Fatalf("wrong output: %s", output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func NewServiceDeleteCommand(p *commands.KnParams) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
namespace, err := commands.GetNamespace(cmd)
|
namespace, err := p.GetNamespace(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func NewServiceDescribeCommand(p *commands.KnParams) *cobra.Command {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, err := commands.GetNamespace(cmd)
|
namespace, err := p.GetNamespace(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func NewServiceListCommand(p *commands.KnParams) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
namespace, err := commands.GetNamespace(cmd)
|
namespace, err := p.GetNamespace(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ func NewServiceUpdateCommand(p *commands.KnParams) *cobra.Command {
|
||||||
return errors.New("requires the service name.")
|
return errors.New("requires the service name.")
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, err := commands.GetNamespace(cmd)
|
namespace, err := p.GetNamespace(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,14 @@ import (
|
||||||
client_testing "k8s.io/client-go/testing"
|
client_testing "k8s.io/client-go/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const FakeNamespace = "current"
|
||||||
|
|
||||||
func CreateTestKnCommand(cmd *cobra.Command, knParams *KnParams) (*cobra.Command, *fake.FakeServingV1alpha1, *bytes.Buffer) {
|
func CreateTestKnCommand(cmd *cobra.Command, knParams *KnParams) (*cobra.Command, *fake.FakeServingV1alpha1, *bytes.Buffer) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
fakeServing := &fake.FakeServingV1alpha1{&client_testing.Fake{}}
|
fakeServing := &fake.FakeServingV1alpha1{&client_testing.Fake{}}
|
||||||
knParams.Output = buf
|
knParams.Output = buf
|
||||||
knParams.ServingFactory = func() (serving.ServingV1alpha1Interface, error) { return fakeServing, nil }
|
knParams.ServingFactory = func() (serving.ServingV1alpha1Interface, error) { return fakeServing, nil }
|
||||||
|
knParams.NamespaceFactory = func() (string, error) { return FakeNamespace, nil }
|
||||||
knCommand := newKnCommand(cmd, knParams)
|
knCommand := newKnCommand(cmd, knParams)
|
||||||
return knCommand, fakeServing, buf
|
return knCommand, fakeServing, buf
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +59,7 @@ Eventing: Manage event subscriptions and channels. Connect up event sources.`,
|
||||||
rootCmd.SetOutput(params.Output)
|
rootCmd.SetOutput(params.Output)
|
||||||
}
|
}
|
||||||
rootCmd.PersistentFlags().StringVar(&CfgFile, "config", "", "config file (default is $HOME/.kn.yaml)")
|
rootCmd.PersistentFlags().StringVar(&CfgFile, "config", "", "config file (default is $HOME/.kn.yaml)")
|
||||||
rootCmd.PersistentFlags().StringVar(&KubeCfgFile, "kubeconfig", "", "kubectl config file (default is $HOME/.kube/config)")
|
rootCmd.PersistentFlags().StringVar(¶ms.KubeCfgPath, "kubeconfig", "", "kubectl config file (default is $HOME/.kube/config)")
|
||||||
|
|
||||||
rootCmd.AddCommand(subCommand)
|
rootCmd.AddCommand(subCommand)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,23 +24,39 @@ import (
|
||||||
// CfgFile is Kn's config file is the path for the Kubernetes config
|
// CfgFile is Kn's config file is the path for the Kubernetes config
|
||||||
var CfgFile string
|
var CfgFile string
|
||||||
|
|
||||||
// KubeCfgFile is the path for the Kubernetes config
|
|
||||||
var KubeCfgFile string
|
|
||||||
|
|
||||||
// Parameters for creating commands. Useful for inserting mocks for testing.
|
// Parameters for creating commands. Useful for inserting mocks for testing.
|
||||||
type KnParams struct {
|
type KnParams struct {
|
||||||
Output io.Writer
|
Output io.Writer
|
||||||
ServingFactory func() (serving.ServingV1alpha1Interface, error)
|
ServingFactory func() (serving.ServingV1alpha1Interface, error)
|
||||||
|
NamespaceFactory func() (string, error)
|
||||||
|
|
||||||
|
KubeCfgPath string
|
||||||
|
ClientConfig clientcmd.ClientConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *KnParams) Initialize() {
|
func (c *KnParams) Initialize() {
|
||||||
if c.ServingFactory == nil {
|
if c.ServingFactory == nil {
|
||||||
c.ServingFactory = GetConfig
|
c.ServingFactory = c.GetConfig
|
||||||
|
}
|
||||||
|
if c.NamespaceFactory == nil {
|
||||||
|
c.NamespaceFactory = c.CurrentNamespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConfig() (serving.ServingV1alpha1Interface, error) {
|
func (c *KnParams) CurrentNamespace() (string, error) {
|
||||||
config, err := clientcmd.BuildConfigFromFlags("", KubeCfgFile)
|
if c.ClientConfig == nil {
|
||||||
|
c.ClientConfig = c.GetClientConfig()
|
||||||
|
}
|
||||||
|
name, _, err := c.ClientConfig.Namespace()
|
||||||
|
return name, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *KnParams) GetConfig() (serving.ServingV1alpha1Interface, error) {
|
||||||
|
if c.ClientConfig == nil {
|
||||||
|
c.ClientConfig = c.GetClientConfig()
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
config, err := c.ClientConfig.ClientConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -50,3 +66,11 @@ func GetConfig() (serving.ServingV1alpha1Interface, error) {
|
||||||
}
|
}
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *KnParams) GetClientConfig() clientcmd.ClientConfig {
|
||||||
|
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||||
|
if len(c.KubeCfgPath) > 0 {
|
||||||
|
loadingRules.ExplicitPath = c.KubeCfgPath
|
||||||
|
}
|
||||||
|
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/knative/client/pkg/kn/commands"
|
"github.com/knative/client/pkg/kn/commands"
|
||||||
"github.com/knative/client/pkg/kn/commands/revision"
|
"github.com/knative/client/pkg/kn/commands/revision"
|
||||||
|
|
@ -65,7 +64,7 @@ Eventing: Manage event subscriptions and channels. Connect up event sources.`,
|
||||||
rootCmd.SetOutput(p.Output)
|
rootCmd.SetOutput(p.Output)
|
||||||
}
|
}
|
||||||
rootCmd.PersistentFlags().StringVar(&commands.CfgFile, "config", "", "config file (default is $HOME/.kn/config.yaml)")
|
rootCmd.PersistentFlags().StringVar(&commands.CfgFile, "config", "", "config file (default is $HOME/.kn/config.yaml)")
|
||||||
rootCmd.PersistentFlags().StringVar(&commands.KubeCfgFile, "kubeconfig", "", "kubectl config file (default is $HOME/.kube/config)")
|
rootCmd.PersistentFlags().StringVar(&p.KubeCfgPath, "kubeconfig", "", "kubectl config file (default is $HOME/.kube/config)")
|
||||||
|
|
||||||
rootCmd.AddCommand(service.NewServiceCommand(p))
|
rootCmd.AddCommand(service.NewServiceCommand(p))
|
||||||
rootCmd.AddCommand(revision.NewRevisionCommand(p))
|
rootCmd.AddCommand(revision.NewRevisionCommand(p))
|
||||||
|
|
@ -77,28 +76,6 @@ Eventing: Manage event subscriptions and channels. Connect up event sources.`,
|
||||||
return rootCmd
|
return rootCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitializeConfig() {
|
|
||||||
cobra.OnInitialize(initConfig)
|
|
||||||
cobra.OnInitialize(initKubeConfig)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func initKubeConfig() {
|
|
||||||
if commands.KubeCfgFile != "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if kubeEnvConf, ok := os.LookupEnv("KUBECONFIG"); ok {
|
|
||||||
commands.KubeCfgFile = kubeEnvConf
|
|
||||||
} else {
|
|
||||||
home, err := homedir.Dir()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
commands.KubeCfgFile = filepath.Join(home, ".kube", "config")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// initConfig reads in config file and ENV variables if set.
|
// initConfig reads in config file and ENV variables if set.
|
||||||
func initConfig() {
|
func initConfig() {
|
||||||
if commands.CfgFile != "" {
|
if commands.CfgFile != "" {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue