in pkg/options/patchtmpl/patch.go [179:283]
func (a *applier) makePatches(ptObjs, objs []*unstructured.Unstructured, opts options.JSONOptions) ([]*parsedPatch, []*unstructured.Unstructured, error) {
// First parse the objects back into go-objects.
var pts []*bundle.PatchTemplate
for _, o := range ptObjs {
pto := &bundle.PatchTemplate{}
err := converter.FromUnstructured(o).ToObject(pto)
if err != nil {
return nil, nil, fmt.Errorf("while converting object %v to PatchTemplate: %v", pto, err)
}
pts = append(pts, pto)
}
if opts == nil {
opts = options.JSONOptions{}
}
// Next, de-templatize the templates.
var patches []*parsedPatch
for j, pto := range pts {
patchType := bundle.PatchType(pto.PatchType)
switch patchType {
case bundle.StrategicMergePatch, bundle.JSONPatch:
// known types
case "":
// use default
patchType = bundle.StrategicMergePatch
default:
return nil, nil, fmt.Errorf("bad patch type: %s", patchType)
}
useSafeYAMLTemplater := internal.HasSafeYAMLAnnotation(pto.ObjectMeta)
tmpl, err := internal.NewTemplater(fmt.Sprintf("patch-tmpl-%d", j), pto.Template, patchFuncs, useSafeYAMLTemplater)
if err != nil {
return nil, nil, fmt.Errorf("parsing patch template %d, %s: %v", j, pto.Template, err)
}
tmpl = tmpl.Option(a.templateOpts...)
newOpts := opts
if pto.OptionsSchema != nil {
newOpts, err = openapi.ApplyDefaults(opts, pto.OptionsSchema)
if err != nil {
return nil, nil, fmt.Errorf("applying schema defaults for patch template %d, %s: %v", j, pto.Template, err)
}
}
// Detemplatize the patch
var buf bytes.Buffer
err = tmpl.Execute(&buf, newOpts)
if err != nil {
return nil, nil, fmt.Errorf("while applying options to patch template %d: %v", j, err)
}
// Convert the patch into a JSONMap to prepare for Strategic Merge Patch.
by := buf.Bytes()
jsonMap := make(map[string]interface{})
err = converter.FromYAML(by).ToObject(&jsonMap)
if err != nil {
return nil, nil, fmt.Errorf("while converting patch template %d: %v", j, err)
}
// Neither Kind nor APIVersion are allowed as patchable fields in a
// PatchTemplate -- we don't want to change the schema of the objects we're
// patching. So, instead remove them from the PatchTemplate and add them as
// an additional selector parameter (which supports the previous behavior).
pKind := ""
pAPIVersion := ""
if jsonMap["kind"] != nil {
var ok bool
pKind, ok = jsonMap["kind"].(string)
if !ok {
return nil, nil, fmt.Errorf("found non-string type %T for Kind field for patch %s", jsonMap["kind"], string(by))
}
delete(jsonMap, "kind")
}
if jsonMap["apiVersion"] != nil {
var ok bool
pAPIVersion, ok = jsonMap["apiVersion"].(string)
if !ok {
return nil, nil, fmt.Errorf("found a non-string APIVersion field for patch %s", string(by))
}
delete(jsonMap, "apiVersion")
}
selector := pto.Selector
if pKind != "" {
if selector == nil {
selector = &bundle.ObjectSelector{}
}
if pAPIVersion != "" {
pKind = pAPIVersion + "," + pKind
}
selector.Kinds = append(selector.Kinds, pKind)
}
patches = append(patches, &parsedPatch{
raw: by,
jsonMap: jsonMap,
selector: selector,
patchType: patchType,
})
}
return patches, objs, nil
}