Overlay one document on another, or apply a JSON Patch, without losing the file’s comments and layout. A merge patch suits environment overrides; a JSON Patch suits scripted changes with a test guard.
package main import ( "errors" "fmt" "log" oneyaml "oneyaml.dev/go" ) func main() { doc, err := oneyaml.Parse([]byte(`# values.yaml image: repository: registry.example.com/web tag: "1.4.2" # set by CI replicas: 2 resources: limits: cpu: 500m memory: 256Mi `)) if err != nil { log.Fatal(err) } // An environment overlay as a merge patch: objects merge, null deletes. overlay := `{"replicas": 5, "resources": {"limits": {"cpu": null, "memory": "1Gi"}}}` if err := doc.ApplyMergePatch([]byte(overlay)); err != nil { log.Fatal(err) } fmt.Print(doc) // A JSON Patch with a guard, built in Go: `test` must pass or nothing changes. bump := []oneyaml.PatchOp{ oneyaml.PatchTest("/image/tag", "1.4.2"), oneyaml.PatchReplace("/image/tag", "1.5.0"), } if err := doc.Apply(bump...); err != nil { log.Fatal(err) } var tag string _ = doc.Get("/image/tag", &tag) fmt.Println("tag now", tag) // Applied again, the test fails and the document is left as it was. err = doc.Apply(bump...) var ee *oneyaml.EditError fmt.Println("second run refused:", errors.As(err, &ee), err) }
# values.yaml image: repository: registry.example.com/web tag: "1.4.2" # set by CI replicas: 5 resources: limits: memory: 1Gi tag now 1.5.0 second run refused: true oneyaml: patch operation 0 (test "/image/tag"): patch test failed
Good to know
- Atomic. If any operation fails, nothing is applied and the error is an
*EditErrorthat names the operation. - A merge patch merges mappings and replaces everything else.
nulldeletes a key; a list in the patch replaces the whole list. - Only the named values change. The
# set by CIcomment and the quotes around the tag stay. - YAML rules, not JSON rules.
testcompares YAML values, so1and1.0differ, and a write through an alias is refused. ApplyPatchtakes RFC 6902 JSON text;ApplytakesPatchOpvalues built withPatchAdd,PatchRemove,PatchReplace,PatchMove,PatchCopyandPatchTest. The work of a patch is bounded unless you passNoLimits().
Every rule is in Patches.
A longer guide: Apply a JSON Patch to a YAML file.