transforming configMapKeyRef into secretKeyRef with jq

119 views Asked by At

Here is my deploy input

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "spec": {
    "replicas": 1,
    "selector": {
      "matchLabels": {
        "io.kompose.service": "item-api"
      }
    },
    "strategy": {
      "type": "Recreate"
    },
    "template": {
      "spec": {
        "containers": [
          {
            "env": [
              {
                "name": "APP_JWTSECRET",
                "valueFrom": {
                  "configMapKeyRef": {
                    "key": "APP_JWTSECRET",
                    "name": "item-api-env"
                  }
                }
              },
              {
                "name": "SPRING_DATASOURCE_BASEXML_JDBCURL",
                "valueFrom": {
                  "configMapKeyRef": {
                    "key": "SPRING_DATASOURCE_BASEXML_JDBCURL",
                    "name": "item-api-env"
                  }
                }
              }
...

For each item into env, I'd like to transform the configMapKeyRef into secretKeyRefif name contains (SECRET|PASSWORD|KEY) pattern and then replace the secretKeyRef name by the key name into lowcase.

for example:

                "name": "APP_JWTSECRET",
                "valueFrom": {
                  "configMapKeyRef": {
                    "key": "APP_JWTSECRET",
                    "name": "item-api-env"
                  }
                }
              }

would be transformed into

                "name": "APP_JWTSECRET",
                "valueFrom": {
                  "secretKeyRef": {
                    "key": "APP_JWTSECRET",
                    "name": "app-jwtsecret"
                  }
                }
              }

I tried some kind of manipulation with with_entries without any success:

jq -r '.spec.template.spec.containers[].env[]|with_entries(.key |test(PASSWORD|SECRET))'
3

There are 3 answers

0
rickhg12hs On BEST ANSWER

Here's one way you could do it. The containers and env array are rewritten with the desired modification, or kept "as is" if the condition isn't met.

.spec.template.spec.containers
|= map(
    (.env
     |= map(
          if (.name|test("SECRET|PASSWORD|KEY"))
          then .valueFrom
            |= with_entries(.key="secretKeyRef"
                 |.value.name=(.value.key|ascii_downcase|gsub("_";"-"))
               )
          else .
          end
        )
    )? // .
)

Try it on jqplay.org.

2
Inian On

One way to use jq would be to do below.

.spec.template.spec.containers[].env[] |= {name} + 
if .name | test("SECRET|PASSWORD|KEY") then 
    .valueFrom |= ( 
        with_entries(
            if .key == "configMapKeyRef" then .key = "secretKeyRef" end | 
                .value |= {key} + {name: .key|ascii_downcase}
        )
    )
end

jqplay demo - https://jqplay.org/s/UfYQYpJIa6o

2
pmf On
  • Navigate to the desired locations: .spec.template.spec.containers[].env[]?
  • Filter for those matching your criteria: select(.name | test("SECRET|PASSWORD|KEY"))
  • Take those results and go deeper: (…).valueFrom
  • Update it with access to .key and .value: |= with_entries(…)
  • Only if the key matches that name: select(.key == "configMapKeyRef") |= …
  • By redefining key and value: {key: "secretKeyRef", value: …}
  • The new value is based on the previous value, and assigns the lowercase key to name: .value | .name = (.key | ascii_downcase)
(
    .spec.template.spec.containers[].env[]?
    | select(.name | test("SECRET|PASSWORD|KEY"))
)

.valueFrom |= with_entries(select(.key == "configMapKeyRef") |= {
    key: "secretKeyRef", value: (.value | .name = (.key | ascii_downcase))
})
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "spec": {
    "replicas": 1,
    "selector": {
      "matchLabels": {
        "io.kompose.service": "item-api"
      }
    },
    "strategy": {
      "type": "Recreate"
    },
    "template": {
      "spec": {
        "containers": [
          {
            "env": [
              {
                "name": "APP_JWTSECRET",
                "valueFrom": {
                  "secretKeyRef": {
                    "key": "APP_JWTSECRET",
                    "name": "app_jwtsecret"
                  }
                }
              },
              {
                "name": "SPRING_DATASOURCE_BASEXML_JDBCURL",
                "valueFrom": {
                  "configMapKeyRef": {
                    "key": "SPRING_DATASOURCE_BASEXML_JDBCURL",
                    "name": "item-api-env"
                  }
                }
              }
            ]
          }
        ]
      }
    }
  }
}

Demo

Note: I regarded the change from app_jwtsecret to app-jwtsecret a typo.