func objectApplier()

in pkg/options/patchtmpl/patch.go [288:355]


func objectApplier(scheme *PatcherScheme, patches []*parsedPatch) options.ObjHandler {
	return func(obj *unstructured.Unstructured, ref bundle.ComponentReference, _ options.JSONOptions) ([]*unstructured.Unstructured, error) {
		objJSON := obj.Object

		if obj.GetKind() == "PatchTemplate" {
			// Don't process PatchTemplates (possible if includeTemplates is set). In
			// other words, it's not allowed to apply patch templates to patch
			// templates.
			return []*unstructured.Unstructured{obj}, nil
		}

		// TODO(kashomon): Is there a faster way to convert from JSON-Map to string?
		objByt, err := converter.FromObject(objJSON).ToJSON()
		if err != nil {
			// This would be pretty unlikely
			return nil, err
		}

		deserializer := scheme.Codecs.UniversalDeserializer()

		kubeObj, decodeErr := runtime.Decode(deserializer, objByt)
		_, isUnstructured := kubeObj.(*unstructured.Unstructured)
		strategicWillFail := runtime.IsNotRegisteredError(decodeErr) || isUnstructured
		objSchema, objSchemaErr := strategicpatch.NewPatchMetaFromStruct(kubeObj)
		for _, pat := range patches {
			if !canApplyPatch(pat, obj) {
				continue
			}

			var newObjJSON map[string]interface{}
			switch pat.patchType {
			case bundle.JSONPatch:
				if oByt, err := converter.FromObject(objJSON).ToJSON(); err != nil {
					return nil, fmt.Errorf("while converting JSON obj\n%s to bytes: %v", objJSON, err)
				} else if pByt, err := converter.FromObject(pat.jsonMap).ToJSON(); err != nil {
					return nil, fmt.Errorf("while converting patch JSON obj\n%s to bytes: %v", pat.jsonMap, err)
				} else if newObjByt, err := jsonpatch.MergePatch(oByt, pByt); err != nil {
					return nil, fmt.Errorf("while applying JSON merge patch\n%s to \n%s: %v", pat.raw, oByt, err)
				} else if newObjJSON, err = converter.FromJSON(newObjByt).ToJSONMap(); err != nil {
					return nil, fmt.Errorf("while converting bytes\n%s to JSON: %v", newObjByt, err)
				}

			case bundle.StrategicMergePatch:
				if strategicWillFail {
					// Strategic merge patch can't handle unstructured.Unstructured or
					// unregistered objects, so return an error.
					return nil, fmt.Errorf("while converting object %q of kind %q and apiVersion %q: type not registered in scheme", obj.GetName(), obj.GetKind(), obj.GetAPIVersion())
				}
				if objSchemaErr != nil {
					return nil, fmt.Errorf("while getting patch meta from object %s: %v", string(objByt), objSchemaErr)
				}
				if newObjJSON, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(objJSON, pat.jsonMap, objSchema); err != nil {
					return nil, fmt.Errorf("while applying strategic merge patch\n%sto \n%s: %v", pat.raw, objJSON, err)
				}

			default:
				return nil, fmt.Errorf("unknown patch type: %s", pat.patchType)
			}

			objJSON = newObjJSON
		}

		obj = &unstructured.Unstructured{
			Object: runtime.DeepCopyJSON(objJSON),
		}
		return []*unstructured.Unstructured{obj}, nil
	}
}