@@ -35,7 +35,7 @@ func UpdateYamlValue(yamlBytes []byte, path []string, value string) ([]byte, err
35
35
}
36
36
37
37
// Convert the updated YAML node back to YAML bytes.
38
- updatedYAMLBytes , err := yamlMarshal (body )
38
+ updatedYAMLBytes , err := YamlMarshal (body )
39
39
if err != nil {
40
40
return nil , fmt .Errorf ("failed to convert YAML node to bytes: %w" , err )
41
41
}
@@ -100,147 +100,101 @@ func lookupKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) {
100
100
return nil , nil
101
101
}
102
102
103
- // Walks a yaml document to the specified path, and then applies the transformation to that node.
104
- //
105
- // The transform must return true if it made changes to the node.
103
+ // Walks a yaml document from the root node to the specified path, and then applies the transformation to that node.
106
104
// If the requested path is not defined in the document, no changes are made to the document.
107
- //
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
-
105
+ func TransformNode (rootNode * yaml.Node , path []string , transform func (node * yaml.Node ) error ) error {
118
106
// Empty document: nothing to do.
119
- if len (node .Content ) == 0 {
120
- return yamlBytes , nil
107
+ if len (rootNode .Content ) == 0 {
108
+ return nil
121
109
}
122
110
123
- body := node .Content [0 ]
124
-
125
- if didTransform , err := transformNode (body , path , transform ); err != nil || ! didTransform {
126
- return yamlBytes , err
127
- }
111
+ body := rootNode .Content [0 ]
128
112
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 )
113
+ if err := transformNode (body , path , transform ); err != nil {
114
+ return err
133
115
}
134
116
135
- return updatedYAMLBytes , nil
117
+ return nil
136
118
}
137
119
138
120
// 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 ) {
121
+ func transformNode (node * yaml.Node , path []string , transform func (node * yaml.Node ) error ) error {
140
122
if len (path ) == 0 {
141
123
return transform (node )
142
124
}
143
125
144
126
keyNode , valueNode := lookupKey (node , path [0 ])
145
127
if keyNode == nil {
146
- return false , nil
128
+ return nil
147
129
}
148
130
149
131
return transformNode (valueNode , path [1 :], transform )
150
132
}
151
133
152
- // takes a yaml document in bytes , a path to a key, and a new name for the key.
134
+ // Takes the root node of a yaml document, a path to a key, and a new name for the key.
153
135
// 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
-
136
+ func RenameYamlKey (rootNode * yaml.Node , path []string , newKey string ) error {
162
137
// Empty document: nothing to do.
163
- if len (node .Content ) == 0 {
164
- return yamlBytes , nil
138
+ if len (rootNode .Content ) == 0 {
139
+ return nil
165
140
}
166
141
167
- body := node .Content [0 ]
142
+ body := rootNode .Content [0 ]
168
143
169
- if didRename , err := renameYamlKey (body , path , newKey ); err != nil || ! didRename {
170
- return yamlBytes , err
144
+ if err := renameYamlKey (body , path , newKey ); err != nil {
145
+ return err
171
146
}
172
147
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 )
177
- }
178
-
179
- return updatedYAMLBytes , nil
148
+ return nil
180
149
}
181
150
182
151
// Recursive function to rename the YAML key.
183
- func renameYamlKey (node * yaml.Node , path []string , newKey string ) ( bool , error ) {
152
+ func renameYamlKey (node * yaml.Node , path []string , newKey string ) error {
184
153
if node .Kind != yaml .MappingNode {
185
- return false , errors .New ("yaml node in path is not a dictionary" )
154
+ return errors .New ("yaml node in path is not a dictionary" )
186
155
}
187
156
188
157
keyNode , valueNode := lookupKey (node , path [0 ])
189
158
if keyNode == nil {
190
- return false , nil
159
+ return nil
191
160
}
192
161
193
162
// end of path reached: rename key
194
163
if len (path ) == 1 {
195
164
// Check that new key doesn't exist yet
196
165
if newKeyNode , _ := lookupKey (node , newKey ); newKeyNode != nil {
197
- return false , fmt .Errorf ("new key `%s' already exists" , newKey )
166
+ return fmt .Errorf ("new key `%s' already exists" , newKey )
198
167
}
199
168
200
169
keyNode .Value = newKey
201
- return true , nil
170
+ return nil
202
171
}
203
172
204
173
return renameYamlKey (valueNode , path [1 :], newKey )
205
174
}
206
175
207
176
// 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
-
177
+ // callback is expected to modify the node in place
178
+ func Walk (rootNode * yaml.Node , callback func (node * yaml.Node , path string )) error {
219
179
// Empty document: nothing to do.
220
- if len (node .Content ) == 0 {
221
- return yamlBytes , nil
180
+ if len (rootNode .Content ) == 0 {
181
+ return nil
222
182
}
223
183
224
- body := node .Content [0 ]
225
-
226
- if didChange , err := walk (body , "" , callback ); err != nil || ! didChange {
227
- return yamlBytes , err
228
- }
184
+ body := rootNode .Content [0 ]
229
185
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 )
186
+ if err := walk (body , "" , callback ); err != nil {
187
+ return err
234
188
}
235
189
236
- return updatedYAMLBytes , nil
190
+ return nil
237
191
}
238
192
239
- func walk (node * yaml.Node , path string , callback func (* yaml.Node , string ) bool ) ( bool , error ) {
240
- didChange := callback (node , path )
193
+ func walk (node * yaml.Node , path string , callback func (* yaml.Node , string )) error {
194
+ callback (node , path )
241
195
switch node .Kind {
242
196
case yaml .DocumentNode :
243
- return false , errors .New ("Unexpected document node in the middle of a yaml tree" )
197
+ return errors .New ("Unexpected document node in the middle of a yaml tree" )
244
198
case yaml .MappingNode :
245
199
for i := 0 ; i < len (node .Content ); i += 2 {
246
200
name := node .Content [i ].Value
@@ -251,31 +205,29 @@ func walk(node *yaml.Node, path string, callback func(*yaml.Node, string) bool)
251
205
} else {
252
206
childPath = fmt .Sprintf ("%s.%s" , path , name )
253
207
}
254
- didChangeChild , err := walk (childNode , childPath , callback )
208
+ err := walk (childNode , childPath , callback )
255
209
if err != nil {
256
- return false , err
210
+ return err
257
211
}
258
- didChange = didChange || didChangeChild
259
212
}
260
213
case yaml .SequenceNode :
261
214
for i := 0 ; i < len (node .Content ); i ++ {
262
215
childPath := fmt .Sprintf ("%s[%d]" , path , i )
263
- didChangeChild , err := walk (node .Content [i ], childPath , callback )
216
+ err := walk (node .Content [i ], childPath , callback )
264
217
if err != nil {
265
- return false , err
218
+ return err
266
219
}
267
- didChange = didChange || didChangeChild
268
220
}
269
221
case yaml .ScalarNode :
270
222
// nothing to do
271
223
case yaml .AliasNode :
272
- return false , errors .New ("Alias nodes are not supported" )
224
+ return errors .New ("Alias nodes are not supported" )
273
225
}
274
226
275
- return didChange , nil
227
+ return nil
276
228
}
277
229
278
- func yamlMarshal (node * yaml.Node ) ([]byte , error ) {
230
+ func YamlMarshal (node * yaml.Node ) ([]byte , error ) {
279
231
var buffer bytes.Buffer
280
232
encoder := yaml .NewEncoder (& buffer )
281
233
encoder .SetIndent (2 )
0 commit comments