diff --git a/internal/authentication/kubernetes/client.go b/internal/authentication/kubernetes/client.go index d5b732487c..1648599363 100644 --- a/internal/authentication/kubernetes/client.go +++ b/internal/authentication/kubernetes/client.go @@ -1,5 +1,5 @@ /* -Copyright 2021 The Dapr Authors +Copyright 2023 The Dapr Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -14,9 +14,9 @@ limitations under the License. package kubernetes import ( - "flag" "os" "path/filepath" + "strings" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -31,17 +31,35 @@ const ( envVarName = "KUBECONFIG" ) -func getKubeconfigPath(log logger.Logger) string { - // Check if the path is set via the CLI flag `-kubeconfig` - // This is deprecated +var defaultKubeConfig string + +func init() { + if home := homedir.HomeDir(); home != "" { + defaultKubeConfig = filepath.Join(home, ".kube", "config") + } +} + +func getKubeconfigPath(log logger.Logger, args []string) string { + // Check if the path is set via the CLI flag `--kubeconfig` + // This is deprecated but kept for backwards compatibility var cliVal string - fs := flag.NewFlagSet(cliFlagName, flag.ContinueOnError) - fs.StringVar(&cliVal, cliFlagName, "", "absolute path to the kubeconfig file") - _ = fs.Parse(os.Args) - cliFlag := fs.Lookup(cliFlagName) - if cliFlag != nil && cliFlag.Value.String() != "" { - log.Warn("Setting kubeconfig using the CLI flag --kubeconfig is deprecated and will be removed in a future version") - return cliFlag.Value.String() + for i, a := range args { + parts := strings.SplitN(a, "=", 2) + if parts[0] == "-"+cliFlagName || parts[0] == "--"+cliFlagName { + // Case: "--kubeconfig=val" or "-kubeconfig=val" + if len(parts) == 2 { + cliVal = parts[1] + break + } else if len(args) > (i+1) && !strings.HasPrefix(args[i+1], "-") { + // Case: "--kubeconfig val" or "-kubeconfig val" + cliVal = args[i+1] + break + } + } + } + if cliVal != "" { + log.Warnf("Setting kubeconfig using the CLI flag '--%s' is deprecated and will be removed in a future version", cliFlagName) + return cliVal } // Check if we have the KUBECONFIG env var @@ -51,18 +69,14 @@ func getKubeconfigPath(log logger.Logger) string { } // Return the default value - home := homedir.HomeDir() - if home != "" { - return filepath.Join(home, ".kube", "config") - } - return "" + return defaultKubeConfig } // GetKubeClient returns a kubernetes client. func GetKubeClient(log logger.Logger) (*kubernetes.Clientset, error) { conf, err := rest.InClusterConfig() if err != nil { - conf, err = clientcmd.BuildConfigFromFlags("", getKubeconfigPath(log)) + conf, err = clientcmd.BuildConfigFromFlags("", getKubeconfigPath(log, os.Args)) if err != nil { return nil, err } diff --git a/internal/authentication/kubernetes/client_test.go b/internal/authentication/kubernetes/client_test.go new file mode 100644 index 0000000000..456a9b75c1 --- /dev/null +++ b/internal/authentication/kubernetes/client_test.go @@ -0,0 +1,61 @@ +/* +Copyright 2023 The Dapr Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubernetes + +import ( + "io" + "strings" + "testing" + + "github.com/dapr/kit/logger" +) + +func TestGetKubeconfigPath(t *testing.T) { + log := logger.NewLogger("test") + log.SetOutput(io.Discard) + tests := []struct { + name string + args []string + env string + want string + }{ + {name: "return default value", want: defaultKubeConfig}, + {name: "CLI flag -kubeconfig cli.yaml", args: []string{"binary", "-kubeconfig", "cli.yaml"}, want: "cli.yaml"}, + {name: "CLI flag -kubeconfig=cli.yaml", args: []string{"binary", "-kubeconfig=cli.yaml"}, want: "cli.yaml"}, + {name: "CLI flag --kubeconfig cli.yaml", args: []string{"binary", "--kubeconfig", "cli.yaml"}, want: "cli.yaml"}, + {name: "CLI flag --kubeconfig=cli.yaml", args: []string{"binary", "--kubeconfig=cli.yaml"}, want: "cli.yaml"}, + {name: "CLI flag --kubeconfig cli.yaml not as last", args: []string{"binary", "--kubeconfig", "cli.yaml", "--foo", "example"}, want: "cli.yaml"}, + {name: "CLI flag --kubeconfig=cli.yaml not as last", args: []string{"binary", "--kubeconfig=cli.yaml", "--foo", "example"}, want: "cli.yaml"}, + {name: "CLI flag --kubeconfig with no value as last", args: []string{"binary", "--kubeconfig"}, want: defaultKubeConfig}, + {name: "CLI flag --kubeconfig with no value and more flags", args: []string{"binary", "--kubeconfig", "--foo"}, want: defaultKubeConfig}, + {name: "env var", env: "KUBECONFIG=env.yaml", want: "env.yaml"}, + {name: "CLI flag has priority over env var", args: []string{"binary", "-kubeconfig", "cli.yaml"}, env: "KUBECONFIG=env.yaml", want: "cli.yaml"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.env != "" { + parts := strings.SplitN(tt.env, "=", 2) + t.Setenv(parts[0], parts[1]) + } + + args := tt.args + if args == nil { + args = []string{} + } + if got := getKubeconfigPath(log, args); got != tt.want { + t.Errorf("getKubeconfigPath() = %v, want %v", got, tt.want) + } + }) + } +}