Извлечение и группировка переменных env по типу из развертываний k8s с помощью jq

Я пытаюсь извлечь список переменных среды развертывания k8s и объединить переменные среды в группу категорий, используя jq и регулярное выражение.

Пример

развертывание k8s:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test
  name: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
      - name: server
        env:
        - name: DB_MAINDB_HOST
          value: maindb.example.com
        - name: DB_MAINDB_DATABASE
          value: test
        - name: DB_MAINDB_USERNAME
          value: username
        - name: DB_MAINDB_PASSWORD
          value: password
        - name: ES_HOST
          value: es-client.example.com
        - name: ES_INDEX
          value: test
        - name: REDIS_HOST
          value: redis.example.com
        image: bustbox

Желаемый результат

{
  "namespace": "default",
  "name": "test",
  "databases": [
    {
      "name": "DB_MAINDB_DATABASE",
      "value": "test"
    },
    {
      "name": "DB_MAINDB_HOST",
      "value": "maindb.example.com"
    },
    {
      "name": "DB_MAINDB_PASSWORD",
      "value": "password"
    },
    {
      "name": "DB_MAINDB_USERNAME",
      "value": "username"
    }
  ],
  "redis": [
    {
      "name": "REDIS_HOST",
      "value": "redis.example.com"
    }
  ],
  "elasticsearch": [
    {
      "name": "ES_HOST",
      "value": "es-client.example.com"
    },
    {
      "name": "ES_INDEX",
      "value": "test"
    }
  ]
}

Я попытался сделать это с помощью следующей команды:

kubectl get deployments test -o json | jq -r '. |
        {namespace: .metadata.namespace,
        name: .metadata.name,
        databases: (.spec.template.spec.containers[].env | [ map(.) | .[] | select(.name | contains ("DB"))] | sort_by(.name)),
        redis: (.spec.template.spec.containers[].env | [ map(.) | .[] | select(.name | contains ("REDIS"))] | sort_by(.name)),
        elasticsearch: (.spec.template.spec.containers[].env | [ map(.) | .[] | select(.name | test("^(ES_).") or contains ("ELASTIC"))] | sort_by(.name)),
        }'

Я ищу немного более элегантное решение моей проблемы и, кроме того, хочу иметь возможность управлять сопоставлением категорий с соответствующим регулярным выражением в качестве дополнительного ввода для команды.

Спасибо!

Вы можете просто отбросить бесполезные . |, преобразовать [ map(.) | .[] | select(…)] в просто map(select(…)) и вычесть .metadata и .spec.template.spec.containers[].env соответственно.

pmf 09.05.2022 18:16
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
1
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот одна переписка с несколькими дубликатами. Решите для себя, соответствует ли это вашим требованиям к элегантности:

(
  .metadata | {namespace, name}
) + (
  .spec.template.spec.containers[].env | {
    databases: map(select(.name | contains ("DB"))),
    redis: map(select(.name | contains ("REDIS"))),
    elasticsearch: map(select(.name | test("^(ES_).") or contains ("ELASTIC")))
  }
  | map_values(sort_by(.name))
)

Кроме того, вы можете перенести сортировку вперед, чтобы отсортировать нефильтрованный массив только один раз:

(
  .metadata | {namespace, name}
) + (
  .spec.template.spec.containers[].env | sort_by(.name) | {
    databases: map(select(.name | contains ("DB"))),
    redis: map(select(.name | contains ("REDIS"))),
    elasticsearch: map(select(.name | test("^(ES_).") or contains ("ELASTIC")))
  }
)

Другие вопросы по теме