From 742a46948b6665b8b916d7123e67b36787b853f3 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 14 Jan 2020 17:08:44 +0100 Subject: [PATCH] fix(kube): use non global Scheme to convert But instead use a newly initialized Scheme with only Kubernetes native resources added. This ensures the 3-way-merge patch strategy is not accidentally chosen for custom resources due to them being added to the global Scheme by e.g. versioned clients while using Helm as a package, and not a self-contained binary. Signed-off-by: Hidde Beydals (cherry picked from commit b55224ebb9541b690daca59f6d85867c6e275d75) --- pkg/kube/converter.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) 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 +}