1package yamlpatch 2 3import ( 4 "fmt" 5 6 yaml "gopkg.in/yaml.v2" 7) 8 9// Patch is an ordered collection of operations. 10type Patch []Operation 11 12// DecodePatch decodes the passed YAML document as if it were an RFC 6902 patch 13func DecodePatch(bs []byte) (Patch, error) { 14 var p Patch 15 16 err := yaml.Unmarshal(bs, &p) 17 if err != nil { 18 return nil, err 19 } 20 21 return p, nil 22} 23 24// Apply returns a YAML document that has been mutated per the patch 25func (p Patch) Apply(doc []byte) ([]byte, error) { 26 var iface interface{} 27 err := yaml.Unmarshal(doc, &iface) 28 if err != nil { 29 return nil, fmt.Errorf("failed unmarshaling doc: %s\n\n%s", string(doc), err) 30 } 31 32 var c Container 33 c = NewNode(&iface).Container() 34 35 for _, op := range p { 36 pathfinder := NewPathFinder(c) 37 if op.Path.ContainsExtendedSyntax() { 38 paths := pathfinder.Find(string(op.Path)) 39 if paths == nil { 40 return nil, fmt.Errorf("could not expand pointer: %s", op.Path) 41 } 42 43 for _, path := range paths { 44 newOp := op 45 newOp.Path = OpPath(path) 46 err = newOp.Perform(c) 47 if err != nil { 48 return nil, err 49 } 50 } 51 } else { 52 err = op.Perform(c) 53 if err != nil { 54 return nil, err 55 } 56 } 57 } 58 59 return yaml.Marshal(c) 60} 61