@@ -35,7 +35,7 @@ func UpdateYamlValue(yamlBytes []byte, path []string, value string) ([]byte, err
3535 }
3636
3737 // Convert the updated YAML node back to YAML bytes.
38- updatedYAMLBytes , err := yamlMarshal (body )
38+ updatedYAMLBytes , err := YamlMarshal (body )
3939 if err != nil {
4040 return nil , fmt .Errorf ("failed to convert YAML node to bytes: %w" , err )
4141 }
@@ -100,83 +100,57 @@ func lookupKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) {
100100 return nil , nil
101101}
102102
103- // Walks a yaml document to the specified path, and then applies the transformation to that node.
103+ // Walks a yaml document from the root node to the specified path, and then applies the transformation to that node.
104104//
105105// The transform must return true if it made changes to the node.
106106// If the requested path is not defined in the document, no changes are made to the document.
107107//
108- // If no changes are made, the original document is returned.
109- // If changes are made, a newly marshalled document is returned. (This may result in different indentation for all nodes)
110- func TransformNode (yamlBytes []byte , path []string , transform func (node * yaml.Node ) (bool , error )) ([]byte , error ) {
111- // Parse the YAML file.
112- var node yaml.Node
113- err := yaml .Unmarshal (yamlBytes , & node )
114- if err != nil {
115- return nil , fmt .Errorf ("failed to parse YAML: %w" , err )
116- }
117-
108+ // Returns true if the transform function made changes to any node
109+ func TransformNode (rootNode * yaml.Node , path []string , transform func (node * yaml.Node ) error ) error {
118110 // Empty document: nothing to do.
119- if len (node .Content ) == 0 {
120- return yamlBytes , nil
111+ if len (rootNode .Content ) == 0 {
112+ return nil
121113 }
122114
123- body := node .Content [0 ]
115+ body := rootNode .Content [0 ]
124116
125- if didTransform , err := transformNode (body , path , transform ); err != nil || ! didTransform {
126- return yamlBytes , err
117+ if err := transformNode (body , path , transform ); err != nil {
118+ return err
127119 }
128120
129- // Convert the updated YAML node back to YAML bytes.
130- updatedYAMLBytes , err := yamlMarshal (body )
131- if err != nil {
132- return nil , fmt .Errorf ("failed to convert YAML node to bytes: %w" , err )
133- }
134-
135- return updatedYAMLBytes , nil
121+ return nil
136122}
137123
138124// A recursive function to walk down the tree. See TransformNode for more details.
139- func transformNode (node * yaml.Node , path []string , transform func (node * yaml.Node ) ( bool , error )) ( bool , error ) {
125+ func transformNode (node * yaml.Node , path []string , transform func (node * yaml.Node ) error ) error {
140126 if len (path ) == 0 {
141127 return transform (node )
142128 }
143129
144130 keyNode , valueNode := lookupKey (node , path [0 ])
145131 if keyNode == nil {
146- return false , nil
132+ return nil
147133 }
148134
149135 return transformNode (valueNode , path [1 :], transform )
150136}
151137
152- // takes a yaml document in bytes , a path to a key, and a new name for the key.
138+ // Takes the root node of a yaml document, a path to a key, and a new name for the key.
153139// Will rename the key to the new name if it exists, and do nothing otherwise.
154- func RenameYamlKey (yamlBytes []byte , path []string , newKey string ) ([]byte , error ) {
155- // Parse the YAML file.
156- var node yaml.Node
157- err := yaml .Unmarshal (yamlBytes , & node )
158- if err != nil {
159- return nil , fmt .Errorf ("failed to parse YAML: %w for bytes %s" , err , string (yamlBytes ))
160- }
161-
140+ // Returns true if it found the old path and renamed the key
141+ func RenameYamlKey (rootNode * yaml.Node , path []string , newKey string ) (bool , error ) {
162142 // Empty document: nothing to do.
163- if len (node .Content ) == 0 {
164- return yamlBytes , nil
143+ if len (rootNode .Content ) == 0 {
144+ return false , nil
165145 }
166146
167- body := node .Content [0 ]
147+ body := rootNode .Content [0 ]
168148
169149 if didRename , err := renameYamlKey (body , path , newKey ); err != nil || ! didRename {
170- return yamlBytes , err
171- }
172-
173- // Convert the updated YAML node back to YAML bytes.
174- updatedYAMLBytes , err := yamlMarshal (body )
175- if err != nil {
176- return nil , fmt .Errorf ("failed to convert YAML node to bytes: %w" , err )
150+ return false , err
177151 }
178152
179- return updatedYAMLBytes , nil
153+ return true , nil
180154}
181155
182156// Recursive function to rename the YAML key.
@@ -205,42 +179,27 @@ func renameYamlKey(node *yaml.Node, path []string, newKey string) (bool, error)
205179}
206180
207181// Traverses a yaml document, calling the callback function for each node. The
208- // callback is allowed to modify the node in place, in which case it should
209- // return true. The function returns the original yaml document if none of the
210- // callbacks returned true, and the modified document otherwise.
211- func Walk (yamlBytes []byte , callback func (node * yaml.Node , path string ) bool ) ([]byte , error ) {
212- // Parse the YAML file.
213- var node yaml.Node
214- err := yaml .Unmarshal (yamlBytes , & node )
215- if err != nil {
216- return nil , fmt .Errorf ("failed to parse YAML: %w" , err )
217- }
218-
182+ // callback is expected to modify the node in place
183+ func Walk (rootNode * yaml.Node , callback func (node * yaml.Node , path string )) error {
219184 // Empty document: nothing to do.
220- if len (node .Content ) == 0 {
221- return yamlBytes , nil
185+ if len (rootNode .Content ) == 0 {
186+ return nil
222187 }
223188
224- body := node .Content [0 ]
225-
226- if didChange , err := walk (body , "" , callback ); err != nil || ! didChange {
227- return yamlBytes , err
228- }
189+ body := rootNode .Content [0 ]
229190
230- // Convert the updated YAML node back to YAML bytes.
231- updatedYAMLBytes , err := yamlMarshal (body )
232- if err != nil {
233- return nil , fmt .Errorf ("failed to convert YAML node to bytes: %w" , err )
191+ if err := walk (body , "" , callback ); err != nil {
192+ return err
234193 }
235194
236- return updatedYAMLBytes , nil
195+ return nil
237196}
238197
239- func walk (node * yaml.Node , path string , callback func (* yaml.Node , string ) bool ) ( bool , error ) {
240- didChange := callback (node , path )
198+ func walk (node * yaml.Node , path string , callback func (* yaml.Node , string )) error {
199+ callback (node , path )
241200 switch node .Kind {
242201 case yaml .DocumentNode :
243- return false , errors .New ("Unexpected document node in the middle of a yaml tree" )
202+ return errors .New ("Unexpected document node in the middle of a yaml tree" )
244203 case yaml .MappingNode :
245204 for i := 0 ; i < len (node .Content ); i += 2 {
246205 name := node .Content [i ].Value
@@ -251,31 +210,29 @@ func walk(node *yaml.Node, path string, callback func(*yaml.Node, string) bool)
251210 } else {
252211 childPath = fmt .Sprintf ("%s.%s" , path , name )
253212 }
254- didChangeChild , err := walk (childNode , childPath , callback )
213+ err := walk (childNode , childPath , callback )
255214 if err != nil {
256- return false , err
215+ return err
257216 }
258- didChange = didChange || didChangeChild
259217 }
260218 case yaml .SequenceNode :
261219 for i := 0 ; i < len (node .Content ); i ++ {
262220 childPath := fmt .Sprintf ("%s[%d]" , path , i )
263- didChangeChild , err := walk (node .Content [i ], childPath , callback )
221+ err := walk (node .Content [i ], childPath , callback )
264222 if err != nil {
265- return false , err
223+ return err
266224 }
267- didChange = didChange || didChangeChild
268225 }
269226 case yaml .ScalarNode :
270227 // nothing to do
271228 case yaml .AliasNode :
272- return false , errors .New ("Alias nodes are not supported" )
229+ return errors .New ("Alias nodes are not supported" )
273230 }
274231
275- return didChange , nil
232+ return nil
276233}
277234
278- func yamlMarshal (node * yaml.Node ) ([]byte , error ) {
235+ func YamlMarshal (node * yaml.Node ) ([]byte , error ) {
279236 var buffer bytes.Buffer
280237 encoder := yaml .NewEncoder (& buffer )
281238 encoder .SetIndent (2 )
0 commit comments