Use own scheme rather than mutating a global shared one

Signed-off-by: Mikhail Mazurskiy <mmazurskiy@gitlab.com>
pull/11250/head
Mikhail Mazurskiy 2 years ago
parent e63083492b
commit e3196143e8
No known key found for this signature in database
GPG Key ID: FA7917C48932DD55

@ -20,12 +20,9 @@ import (
"strconv" "strconv"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"k8s.io/client-go/kubernetes/scheme"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
helmversion "helm.sh/helm/v3/internal/version" helmversion "helm.sh/helm/v3/internal/version"
"helm.sh/helm/v3/pkg/kube"
) )
var ( var (
@ -111,13 +108,7 @@ func (v VersionSet) Has(apiVersion string) bool {
} }
func allKnownVersions() VersionSet { func allKnownVersions() VersionSet {
// We should register the built in extension APIs as well so CRDs are groups := kube.NativeScheme().PrioritizedVersionsAllGroups()
// supported in the default version set. This has caused problems with `helm
// template` in the past, so let's be safe
apiextensionsv1beta1.AddToScheme(scheme.Scheme)
apiextensionsv1.AddToScheme(scheme.Scheme)
groups := scheme.Scheme.PrioritizedVersionsAllGroups()
vs := make(VersionSet, 0, len(groups)) vs := make(VersionSet, 0, len(groups))
for _, gv := range groups { for _, gv := range groups {
vs = append(vs, gv.String()) vs = append(vs, gv.String())

@ -30,14 +30,12 @@ import (
"time" "time"
jsonpatch "github.com/evanphx/json-patch" jsonpatch "github.com/evanphx/json-patch"
multierror "github.com/hashicorp/go-multierror"
"github.com/pkg/errors" "github.com/pkg/errors"
batch "k8s.io/api/batch/v1" batch "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
multierror "github.com/hashicorp/go-multierror"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -51,7 +49,6 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
cachetools "k8s.io/client-go/tools/cache" cachetools "k8s.io/client-go/tools/cache"
watchtools "k8s.io/client-go/tools/watch" watchtools "k8s.io/client-go/tools/watch"
@ -77,23 +74,11 @@ type Client struct {
kubeClient *kubernetes.Clientset kubeClient *kubernetes.Clientset
} }
var addToScheme sync.Once
// New creates a new Client. // New creates a new Client.
func New(getter genericclioptions.RESTClientGetter) *Client { func New(getter genericclioptions.RESTClientGetter) *Client {
if getter == nil { if getter == nil {
getter = genericclioptions.NewConfigFlags(true) getter = genericclioptions.NewConfigFlags(true)
} }
// Add CRDs to the scheme. They are missing by default.
addToScheme.Do(func() {
if err := apiextv1.AddToScheme(scheme.Scheme); err != nil {
// This should never happen.
panic(err)
}
if err := apiextv1beta1.AddToScheme(scheme.Scheme); err != nil {
panic(err)
}
})
return &Client{ return &Client{
Factory: cmdutil.NewFactory(getter), Factory: cmdutil.NewFactory(getter),
Log: nopLogger, Log: nopLogger,

@ -40,30 +40,36 @@ func AsVersioned(info *resource.Info) runtime.Object {
// convertWithMapper converts the given object with the optional provided // convertWithMapper converts the given object with the optional provided
// RESTMapping. If no mapping is provided, the default schema versioner is used // RESTMapping. If no mapping is provided, the default schema versioner is used
func convertWithMapper(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object { func convertWithMapper(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object {
s := kubernetesNativeScheme() s := NativeScheme()
var gv = runtime.GroupVersioner(schema.GroupVersions(s.PrioritizedVersionsAllGroups())) var gv = runtime.GroupVersioner(schema.GroupVersions(s.PrioritizedVersionsAllGroups()))
if mapping != nil { if mapping != nil {
gv = mapping.GroupVersionKind.GroupVersion() gv = mapping.GroupVersionKind.GroupVersion()
} }
if obj, err := runtime.ObjectConvertor(s).ConvertToVersion(obj, gv); err == nil { if obj, err := s.ConvertToVersion(obj, gv); err == nil {
return obj return obj
} }
return obj return obj
} }
// kubernetesNativeScheme returns a clean *runtime.Scheme with _only_ Kubernetes // NativeScheme returns a clean *runtime.Scheme with _only_ Kubernetes
// native resources added to it. This is required to break free of custom resources // native resources added to it. This is required to break free of custom resources
// that may have been added to scheme.Scheme due to Helm being used as a package in // that may have been added to scheme.Scheme due to Helm being used as a package in
// combination with e.g. a versioned kube client. If we would not do this, the client // combination with e.g. a versioned kube client. If we would not do this, the client
// may attempt to perform e.g. a 3-way-merge strategy patch for custom resources. // may attempt to perform e.g. a 3-way-merge strategy patch for custom resources.
func kubernetesNativeScheme() *runtime.Scheme { func NativeScheme() *runtime.Scheme {
k8sNativeSchemeOnce.Do(func() { k8sNativeSchemeOnce.Do(func() {
k8sNativeScheme = runtime.NewScheme() k8sNativeScheme = runtime.NewScheme()
scheme.AddToScheme(k8sNativeScheme) if err := scheme.AddToScheme(k8sNativeScheme); err != nil {
panic(err)
}
// API extensions are not in the above scheme set, // API extensions are not in the above scheme set,
// and must thus be added separately. // and must thus be added separately.
apiextensionsv1beta1.AddToScheme(k8sNativeScheme) if err := apiextensionsv1beta1.AddToScheme(k8sNativeScheme); err != nil {
apiextensionsv1.AddToScheme(k8sNativeScheme) panic(err)
}
if err := apiextensionsv1.AddToScheme(k8sNativeScheme); err != nil {
panic(err)
}
}) })
return k8sNativeScheme return k8sNativeScheme
} }

@ -32,7 +32,6 @@ import (
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/cli-runtime/pkg/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
deploymentutil "helm.sh/helm/v3/internal/third_party/k8s.io/kubernetes/deployment/util" deploymentutil "helm.sh/helm/v3/internal/third_party/k8s.io/kubernetes/deployment/util"
) )
@ -155,7 +154,7 @@ func (c *ReadyChecker) IsReady(ctx context.Context, v *resource.Info) (bool, err
return false, err return false, err
} }
crd := &apiextv1beta1.CustomResourceDefinition{} crd := &apiextv1beta1.CustomResourceDefinition{}
if err := scheme.Scheme.Convert(v.Object, crd, nil); err != nil { if err := NativeScheme().Convert(v.Object, crd, nil); err != nil {
return false, err return false, err
} }
if !c.crdBetaReady(*crd) { if !c.crdBetaReady(*crd) {
@ -166,7 +165,7 @@ func (c *ReadyChecker) IsReady(ctx context.Context, v *resource.Info) (bool, err
return false, err return false, err
} }
crd := &apiextv1.CustomResourceDefinition{} crd := &apiextv1.CustomResourceDefinition{}
if err := scheme.Scheme.Convert(v.Object, crd, nil); err != nil { if err := NativeScheme().Convert(v.Object, crd, nil); err != nil {
return false, err return false, err
} }
if !c.crdReady(*crd) { if !c.crdReady(*crd) {

Loading…
Cancel
Save