Skip to content

Instantly share code, notes, and snippets.

@ciis0
Last active March 28, 2022 10:32
Show Gist options
  • Save ciis0/73f517c7565f8a05286a083f43135cd4 to your computer and use it in GitHub Desktop.
Save ciis0/73f517c7565f8a05286a083f43135cd4 to your computer and use it in GitHub Desktop.
@Grab(group='org.yaml', module='snakeyaml', version='1.27')
import org.yaml.snakeyaml.Yaml;
@Grab(group = 'org.slf4j', module = 'slf4j-simple', version = '1.7.27')
import org.slf4j.LoggerFactory
/*
* Groovy script to update *scalar* YAML values without touching the file structure (comments, indent, ...)
*
* snakeyaml's Nodes returned by Yaml#compose inlude start and end "Marks" describing the location the input stream.
* We filter out the nodes we're interested in and update their values based on that indices.
*
* This script specifically updates images.newTag values in a Kustomization YAML.
*
*/
def LOG = LoggerFactory.getLogger(getClass())
def version = "" // ...
def yaml = "" // for demonstrative purposes simply a String
// Yaml#compose() fully consumes it's stream so we need an additional one
def sr = new StringReader(yaml)
def sb = new StringBuffer()
def images = new Yaml()
// representation graph
.compose(new StringReader(yaml))
// assume a mapping node (a list of key-value node tuples) at root
.value
// find "images" tuple
.find { it.keyNode.value == "images" }
// retrieve (mapping) value
.valueNode.value
def bytesRead = 0
char[] buf = null
def seenNodes = []
images.each {
def val = it.value.find { it.keyNode.value == "newTag"}.valueNode
def (start, end) = [val.startMark, val.endMark]
def seen = val in seenNodes
seenNodes << val
LOG.debug "---"
LOG.debug "$val $seen $val.anchor\n$start\n$end\n"
LOG.debug "read $bytesRead"
LOG.debug "start $start.index L$start.line,$start.column (${start.index-bytesRead}) ${start.hashCode()}"
LOG.debug "end $end.index L$end.line,$end.column (${end.index-start.index}) ${end.hashCode()}"
if(seen){ // alias nodes
return
}
// read up content until value start
buf = new char[start.index-bytesRead]
bytesRead += sr.read(buf, 0, buf.length)
sb.append(buf)
// read and throw away old value
buf = new char[end.index-start.index]
bytesRead += sr.read(buf, 0, buf.length)
// write new value
sb.append(/${val.anchor ? "&$val.anchor " : ""}$version/)
}
sb.append(sr.text)
yaml = sb.toString()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment