CSUNNY
CSUNNY

Reputation: 454

Use yq to parse property files data model

I have a YAML file like this

apiVersion: "v1alpha1"
kind: "Druid"
metadata:
  name: druid-dev-cluster
spec:
  common.runtime.properties: |
    # Zookeeper
    druid.zk.service.host=cluster-zk-0.cluster-zk
    druid.zk.paths.base=/druid
    druid.zk.service.compress=false

I want to replace one of the properties in the common.runtime.properties. Is this supported using yq? When I try normally it fails

property=.spec.common.runtime.properties.druid.zk.service.host=cluster-zk-0.cluster-zk
OVERLAY= deploy/overlays/aws/common-runtime-properties.yaml
yq e "${property}" "$OVERLAY"/"$propertyType"

Error: Parsing expression: Lexer error: could not match text starting at 1:55 failing at 1:57.
        unmatched text: "ti"

This works for other properties like

apiVersion: "v1alpha1"
kind: "Druid"
metadata:
  name: druid-dev-cluster
spec:
  nodes:
    brokers:
      nodeType: "broker"
      druid.port: 8088
      ingressAnnotations:
        kubernetes.io/ingress.class: "plb.v1"

Upvotes: 0

Views: 1393

Answers (1)

flyx
flyx

Reputation: 39768

The problems are:

  • | is a YAML literal block scalar. Its content is a single scalar as far as YAML is concerned and hence you cannot path-select into it from yq.
  • Also, the content of | is not YAML, but probably parsed as Java properties file. Therefore, you cannot parse it even with recursively calling yq on the scalar.
  • Also, the path to the scalar is not .spec.common.runtime.properties but .spec."common.runtime.properties" – note how the second part is written as a single scalar in the YAML content, which is not equivalent to having multiple child mappings (even though some Java folks seem to believe that).

That being said, you can of course do something like

export NEW_VALUE=droggeljug
UPDATED_CONTENT=$(\
    yq e '.spec."common.runtime.properties"' test.yaml | \
    sed -re 's/(druid.zk.service.host=)[^\n]*/\1'"$NEW_VALUE"'/g' \
) yq e '.spec."common.runtime.properties" = strenv(UPDATED_CONTENT)' test.yaml

This uses yq to select the scalar containing the properties (line 3), uses sed to update the value druid.zk.service.host to the content of NEW_VALUE (line 4), stores the result in UPDATED_CONTENT (line 2) and then calls yq again updating the value to be the content of UPDATED_CONTENT (line 5).

Upvotes: 2

Related Questions