From ac9cf58afa8ac9385501dc23a45eec09c504b4bf Mon Sep 17 00:00:00 2001 From: Jianbo Sun Date: Tue, 13 Dec 2022 14:53:54 +0800 Subject: [PATCH] Feat: support fallback to kubeconfig namespace when env not set (#5182) Signed-off-by: Jianbo Sun Signed-off-by: Jianbo Sun --- pkg/oam/util/helper.go | 3 +- pkg/utils/common/args.go | 45 ++++++++++++++++++++----- pkg/utils/common/common_test.go | 7 ++++ pkg/utils/common/testdata/testkube.conf | 20 +++++++++++ references/cli/dryrun.go | 2 +- references/cli/env.go | 6 +++- 6 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 pkg/utils/common/testdata/testkube.conf diff --git a/pkg/oam/util/helper.go b/pkg/oam/util/helper.go index f111d9156..25cb8aab6 100644 --- a/pkg/oam/util/helper.go +++ b/pkg/oam/util/helper.go @@ -46,6 +46,7 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/condition" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + types2 "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" ) @@ -297,7 +298,7 @@ func GetDefinitionNamespaceWithCtx(ctx context.Context) string { func SetNamespaceInCtx(ctx context.Context, namespace string) context.Context { if namespace == "" { // compatible with some webhook handlers that maybe receive empty string as app namespace which means `default` namespace - namespace = "default" + namespace = types2.DefaultAppNamespace } ctx = context.WithValue(ctx, AppDefinitionNamespace, namespace) return ctx diff --git a/pkg/utils/common/args.go b/pkg/utils/common/args.go index 41933f9e9..4325a4304 100644 --- a/pkg/utils/common/args.go +++ b/pkg/utils/common/args.go @@ -20,11 +20,12 @@ import ( "fmt" pkgmulticluster "github.com/kubevela/pkg/multicluster" - "k8s.io/client-go/discovery" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/discovery" "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/flowcontrol" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" @@ -38,12 +39,13 @@ import ( // Args is args for controller-runtime client type Args struct { - config *rest.Config - Schema *runtime.Scheme - client client.Client - dm discoverymapper.DiscoveryMapper - pd *packages.PackageDiscover - dc *discovery.DiscoveryClient + config *rest.Config + rawConfig *api.Config + Schema *runtime.Scheme + client client.Client + dm discoverymapper.DiscoveryMapper + pd *packages.PackageDiscover + dc *discovery.DiscoveryClient } // SetConfig insert kubeconfig into Args @@ -72,6 +74,33 @@ func (a *Args) GetConfig() (*rest.Config, error) { return a.config, nil } +// GetRawConfig get raw kubeconfig, if not exist, will create +func (a *Args) GetRawConfig() (*api.Config, error) { + if a.rawConfig != nil { + return a.rawConfig, nil + } + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + raw, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + loadingRules, nil).RawConfig() + if err != nil { + return nil, err + } + return &raw, nil +} + +// GetNamespaceFromConfig will get namespace from kube config +func (a *Args) GetNamespaceFromConfig() string { + conf, err := a.GetRawConfig() + if err != nil || conf == nil || conf.Contexts == nil { + return "" + } + ctx, ok := conf.Contexts[conf.CurrentContext] + if !ok { + return "" + } + return ctx.Namespace +} + // SetClient set custom client func (a *Args) SetClient(c client.Client) { a.client = c diff --git a/pkg/utils/common/common_test.go b/pkg/utils/common/common_test.go index 016dc4817..0049e7456 100644 --- a/pkg/utils/common/common_test.go +++ b/pkg/utils/common/common_test.go @@ -589,3 +589,10 @@ func TestHTTPGetKubernetesObjects(t *testing.T) { assert.Equal(t, "busybox", uns[1].GetName()) assert.Equal(t, "ConfigMap", uns[1].GetKind()) } + +func TestGetRawConfig(t *testing.T) { + assert.NoError(t, os.Setenv("KUBECONFIG", filepath.Join("testdata", "testkube.conf"))) + ag := Args{} + ns := ag.GetNamespaceFromConfig() + assert.Equal(t, "prod", ns) +} diff --git a/pkg/utils/common/testdata/testkube.conf b/pkg/utils/common/testdata/testkube.conf new file mode 100644 index 000000000..ae44a6c07 --- /dev/null +++ b/pkg/utils/common/testdata/testkube.conf @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: +- cluster: + server: https://127.0.0.1:6443 + certificate-authority-data: YWJjMQ== + name: kubernetes +contexts: +- context: + cluster: kubernetes + user: "kubernetes-admin" + namespace: "prod" + name: kubernetes-admin +current-context: kubernetes-admin +kind: Config +preferences: {} +users: +- name: "kubernetes-admin" + user: + client-certificate-data: S1N6 + client-key-data: S1N6 \ No newline at end of file diff --git a/references/cli/dryrun.go b/references/cli/dryrun.go index b3519b451..be4b1abe0 100644 --- a/references/cli/dryrun.go +++ b/references/cli/dryrun.go @@ -76,7 +76,7 @@ You can also specify a remote url for app: } // Set the namespace to default to match behavior of `GetFlagNamespaceOrEnv` - namespace = "default" + namespace = types.DefaultAppNamespace } buff, err := DryRunApplication(o, c, namespace) diff --git a/references/cli/env.go b/references/cli/env.go index 9ed014c21..8dad75a52 100644 --- a/references/cli/env.go +++ b/references/cli/env.go @@ -251,7 +251,11 @@ func GetFlagEnvOrCurrent(cmd *cobra.Command, args common.Args) (*types.EnvMeta, if err != nil { // ignore this error and return a default value // nolint:nilerr - return &types.EnvMeta{Name: "", Namespace: "default"}, nil + ns := args.GetNamespaceFromConfig() + if ns == "" { + ns = types.DefaultAppNamespace + } + return &types.EnvMeta{Name: "", Namespace: ns}, nil } return cur, nil }