Add a flag to switch between patch strategy for unstructured

Signed-off-by: wxdao <waxiadao@gmail.com>
pull/9938/head
wxdao 4 years ago
parent c88c081f47
commit e28152f816

@ -163,6 +163,8 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
}
actionConfig.RegistryClient = registryClient
actionConfig.UseThreeWayMergePatchForUnstructured = settings.UseThreeWayMergePatchForUnstructured
// Add subcommands
cmd.AddCommand(
// chart commands

@ -16,6 +16,7 @@ require (
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible
github.com/docker/go-units v0.4.0
github.com/evanphx/json-patch v4.9.0+incompatible
github.com/gobwas/glob v0.2.3
github.com/gofrs/flock v0.8.0
github.com/gosuri/uitable v0.0.4

@ -94,6 +94,10 @@ type Configuration struct {
// Capabilities describes the capabilities of the Kubernetes cluster.
Capabilities *chartutil.Capabilities
// UseThreeWayMergePatchForUnstructured controls whether to use three way merge patch
// for unstructured (CR, CRD etc.) objects.
UseThreeWayMergePatchForUnstructured bool
Log func(string, ...interface{})
}
@ -365,6 +369,7 @@ func (cfg *Configuration) recordRelease(r *release.Release) {
func (cfg *Configuration) Init(getter genericclioptions.RESTClientGetter, namespace, helmDriver string, log DebugLog) error {
kc := kube.New(getter)
kc.Log = log
kc.UseThreeWayMergePatchForUnstructured = cfg.UseThreeWayMergePatchForUnstructured
lazyClient := &lazyClient{
namespace: namespace,

@ -68,6 +68,9 @@ type EnvSettings struct {
PluginsDirectory string
// MaxHistory is the max release history maintained.
MaxHistory int
// UseThreeWayMergePatchForUnstructured controls whether to use three way merge patch
// for unstructured (CR, CRD etc.) objects.
UseThreeWayMergePatchForUnstructured bool
}
func New() *EnvSettings {
@ -86,6 +89,7 @@ func New() *EnvSettings {
RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")),
}
env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG"))
env.UseThreeWayMergePatchForUnstructured, _ = strconv.ParseBool(os.Getenv("HELM_USE_THREE_WAY_MERGE_PATCH_FOR_UNSTRUCTURED"))
// bind to kubernetes config flags
env.config = &genericclioptions.ConfigFlags{
@ -115,6 +119,7 @@ func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.RegistryConfig, "registry-config", s.RegistryConfig, "path to the registry config file")
fs.StringVar(&s.RepositoryConfig, "repository-config", s.RepositoryConfig, "path to the file containing repository names and URLs")
fs.StringVar(&s.RepositoryCache, "repository-cache", s.RepositoryCache, "path to the file containing cached repository indexes")
fs.BoolVar(&s.UseThreeWayMergePatchForUnstructured, "use-three-way-merge-patch-for-unstructured", s.UseThreeWayMergePatchForUnstructured, "use three way merge patch for unstructured (CR, CRD etc.) objects")
}
func envOr(name, def string) string {

@ -27,6 +27,7 @@ import (
"sync"
"time"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
batch "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
@ -69,6 +70,10 @@ type Client struct {
// Namespace allows to bypass the kubeconfig file for the choice of the namespace
Namespace string
// UseThreeWayMergePatchForUnstructured controls whether to use three way merge patch
// for unstructured (CR, CRD etc.) objects
UseThreeWayMergePatchForUnstructured bool
kubeClient *kubernetes.Clientset
}
@ -418,7 +423,7 @@ func deleteResource(info *resource.Info) error {
return err
}
func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) {
func createPatch(target *resource.Info, current runtime.Object, useThreeWayMergePatchForUnstructured bool) ([]byte, types.PatchType, error) {
oldData, err := json.Marshal(current)
if err != nil {
return nil, types.StrategicMergePatchType, errors.Wrap(err, "serializing current configuration")
@ -446,7 +451,7 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P
// Unstructured objects, such as CRDs, may not have an not registered error
// returned from ConvertToVersion. Anything that's unstructured should
// use the jsonmergepatch.CreateThreeWayJSONMergePatch. Strategic Merge Patch is not supported
// use generic JSON merge patch. Strategic Merge Patch is not supported
// on objects like CRDs.
_, isUnstructured := versionedObject.(runtime.Unstructured)
@ -455,6 +460,7 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P
if isUnstructured || isCRD {
// fall back to generic JSON merge patch
if useThreeWayMergePatchForUnstructured {
// from https://github.com/kubernetes/kubectl/blob/b83b2ec7d15f286720bccf7872b5c72372cb8e80/pkg/cmd/apply/patcher.go#L129
preconditions := []mergepatch.PreconditionFunc{mergepatch.RequireKeyUnchanged("apiVersion"),
mergepatch.RequireKeyUnchanged("kind"), mergepatch.RequireMetadataKeyUnchanged("name")}
@ -464,6 +470,9 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P
}
return patch, types.MergePatchType, err
}
patch, err := jsonpatch.CreateMergePatch(oldData, newData)
return patch, types.MergePatchType, err
}
patchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObject)
if err != nil {
@ -490,7 +499,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
}
c.Log("Replaced %q with kind %s for kind %s", target.Name, currentObj.GetObjectKind().GroupVersionKind().Kind, kind)
} else {
patch, patchType, err := createPatch(target, currentObj)
patch, patchType, err := createPatch(target, currentObj, c.UseThreeWayMergePatchForUnstructured)
if err != nil {
return errors.Wrap(err, "failed to create patch")
}

Loading…
Cancel
Save