package patch import ( "sync" "github.com/rancher/wrangler/pkg/gvk" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/client-go/kubernetes/scheme" ) var ( patchCache = map[schema.GroupVersionKind]patchCacheEntry{} patchCacheLock = sync.Mutex{} ) type patchCacheEntry struct { patchType types.PatchType lookup strategicpatch.LookupPatchMeta } func isJSONPatch(patch []byte) bool { // a JSON patch is a list return len(patch) > 0 && patch[0] == '[' } func GetPatchStyle(original, patch []byte) (types.PatchType, strategicpatch.LookupPatchMeta, error) { if isJSONPatch(patch) { return types.JSONPatchType, nil, nil } gvk, ok, err := gvk.Detect(original) if err != nil { return "", nil, err } if !ok { return types.MergePatchType, nil, nil } return GetMergeStyle(gvk) } func GetMergeStyle(gvk schema.GroupVersionKind) (types.PatchType, strategicpatch.LookupPatchMeta, error) { var ( patchType types.PatchType lookupPatchMeta strategicpatch.LookupPatchMeta ) patchCacheLock.Lock() entry, ok := patchCache[gvk] patchCacheLock.Unlock() if ok { return entry.patchType, entry.lookup, nil } versionedObject, err := scheme.Scheme.New(gvk) if runtime.IsNotRegisteredError(err) { patchType = types.MergePatchType } else if err != nil { return patchType, nil, err } else { patchType = types.StrategicMergePatchType lookupPatchMeta, err = strategicpatch.NewPatchMetaFromStruct(versionedObject) if err != nil { return patchType, nil, err } } patchCacheLock.Lock() patchCache[gvk] = patchCacheEntry{ patchType: patchType, lookup: lookupPatchMeta, } patchCacheLock.Unlock() return patchType, lookupPatchMeta, nil }