find specific field and insert new value with jq

Viewed 110

I have this command in a bash script

kubectl get svc --selector='app.kubernetes.io/component=sentinel' --all-namespaces -o json |
jq -r '
.items
   | map(
   {label:.metadata.name,
   sentinels: [{host:(.metadata.name + "." + .metadata.namespace + "." + "svc" + "." + "cluster" + "." + "local"),port: .spec.ports[0].port}],
   sentinelName:"mymaster",
   sentinelPassword: ""
   dbIndex: 0
   })
| {connections: . }' /
>local.json

which produces something like this output

{
  "connections": [
    {
      "label": "Redis1",
      "sentinels": [
        {
          "host": "Redis1.default.svc.cluster.local",
          "port": 26379
        }
      ],
      "sentinelName": "mymaster",
      "sentinelPassword": "",
      "dbIndex": 0
    },
    {
      "label": "Redis2",
      "sentinels": [
        {
          "host": "Redis2.development.svc.cluster.local",
          "port": 26379
        }
      ],
      "sentinelName": "mymaster",
      "sentinelPassword": "",
      "dbIndex": 0
    }
  ]
}

This config file is injected into container via an init-container so Redis-Commander fetches the redis instances without the user having to manually input any connection config data. This works fine however but one of the instances requires a sentinelPassword value.

I can fetch the password using kubectl get secret but I'm trying to figure out how to insert that password into the config file for the particular instance that requires it.

I've been trying something along the lines of this but getting my jq syntax wrong. Any help or alternative ways of going around would be appreciated.

#store output in var
JSON=$(kubectl get svc --selector='app.kubernetes.io/component=sentinel' --all-namespaces -o json |
jq -r '
.items
   | map(
   {label:.metadata.name,
   sentinels: [{host:(.metadata.name + "." + .metadata.namespace + "." + "svc" + "." + "cluster" + "." + "local"),port: .spec.ports[0].port}],
   sentinelName:"mymaster",
   sentinelPassword: "",
   dbIndex: 0
   })
| {connections: . }')

# Find instance by their host value which is unique. (Can't figure out how to do this bit)
  if $JSON host name contains "Redis2.development.svc.cluster.local"
#then do something like this
    "$JSON" | jq '.[]'| .sentinelPassword = "$password" #var stored from kubectl get secret cmd

#save output to file
"$JSON">/local.json

1 Answers

Assuming for the moment that you want to invoke jq on the sample JSON (local.json) as shown, you could run:

password=mypassword
< local.json jq --arg password "$password" '
  .connections[] |= if any(.sentinels[].host; index("Redis2.development.svc.cluster.local"))
                    then .sentinelPassword = $password else . end'

However, if possible, it would probably be better to invoke jq just once.

Related