yq - is it possible to create a new key/value pair using an existing value whilst returning the whole yaml object?

Viewed 36

Currently using yq (mikefarah/yq/ - version 4.27.2) and having trouble modifying inline an existing yaml file.

What I'm trying to do:

  • select the labels field
  • if labels contains a field named monitored_item, create a key named affectedCi and use the value of monitored_item
  • if labels does not contain a field named monitored_item, create a key named affectedCi with the value {{ $labels.affected_ci }}
  • return the whole yaml object with changes made inline

jobs-prometheusRule.yaml

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    app: jobs
    prometheus: k8s
    role: alert-rules
  name: jobs-rules
  namespace: ops
spec:
  groups:
  - name: job-detailed
    rules:
    - alert: JobInstanceFailed
      annotations:
        description: Please check the status of the {{ $labels.app_name }} job {{ $labels.job_name }} as it has failed.
        summary: Job has failed
      expr: (process_failed{context="job_failed"} + on(app_name, job_name) group_left(severity)(topk by(app_name, job_name) (1, property{context="job_max_allowed_failures"}))) == 1
      for: 1m
      labels:
        monitored_item: '{{ $labels.app_name }} job {{ $labels.job_name }}'
        severity: '{{ $labels.severity }}'

I've scoured through the docs and stack overflow with no luck - below is as far as i've been able to get.

yq command:

yq '(.spec.groups[].rules[] | select(.labels | has("monitored_item")) | .labels.affectedCi) |= .labels.monitored_item ' jobs-prometheusRule.yaml

The output returns the whole yaml object with the field affectedCi: null instead of the specified values

Anyone able to help?

1 Answers

You could use with to update, and // for fall-back:

yq 'with(
  .spec.groups[].rules[] | select(.labels).labels;
  .affectedCi = .monitored_item // "{{ $labels.affected_ci }}"
)' jobs-prometheusRule.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    app: jobs
    prometheus: k8s
    role: alert-rules
  name: jobs-rules
  namespace: ops
spec:
  groups:
    - name: job-detailed
      rules:
        - alert: JobInstanceFailed
          annotations:
            description: Please check the status of the {{ $labels.app_name }} job {{ $labels.job_name }} as it has failed.
            summary: Job has failed
          expr: (process_failed{context="job_failed"} + on(app_name, job_name) group_left(severity)(topk by(app_name, job_name) (1, property{context="job_max_allowed_failures"}))) == 1
          for: 1m
          labels:
            monitored_item: '{{ $labels.app_name }} job {{ $labels.job_name }}'
            severity: '{{ $labels.severity }}'
            affectedCi: '{{ $labels.app_name }} job {{ $labels.job_name }}'
Related