diff --git a/pkg/kube/converter.go b/pkg/kube/converter.go index a5a6ae1f7..7f062213c 100644 --- a/pkg/kube/converter.go +++ b/pkg/kube/converter.go @@ -17,9 +17,12 @@ limitations under the License. package kube // import "helm.sh/helm/v3/pkg/kube" import ( + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/cli-runtime/pkg/resource" "k8s.io/client-go/kubernetes/scheme" ) @@ -33,12 +36,28 @@ func AsVersioned(info *resource.Info) runtime.Object { // convertWithMapper converts the given object with the optional provided // RESTMapping. If no mapping is provided, the default schema versioner is used func convertWithMapper(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object { - var gv = runtime.GroupVersioner(schema.GroupVersions(scheme.Scheme.PrioritizedVersionsAllGroups())) + s := kubernetesNativeScheme() + var gv = runtime.GroupVersioner(schema.GroupVersions(s.PrioritizedVersionsAllGroups())) if mapping != nil { gv = mapping.GroupVersionKind.GroupVersion() } - if obj, err := runtime.ObjectConvertor(scheme.Scheme).ConvertToVersion(obj, gv); err == nil { + if obj, err := runtime.ObjectConvertor(s).ConvertToVersion(obj, gv); err == nil { return obj } return obj } + +// kubernetesNativeScheme returns a clean *runtime.Scheme with _only_ Kubernetes +// 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 +// 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. +func kubernetesNativeScheme() *runtime.Scheme { + s := runtime.NewScheme() + utilruntime.Must(scheme.AddToScheme(s)) + // API extensions are not in the above scheme set, + // and must thus be added separately. + utilruntime.Must(apiextensionsv1beta1.AddToScheme(s)) + utilruntime.Must(apiextensionsv1.AddToScheme(s)) + return s +}