ДОБАВЬТЕ / УДАЛИТЕ внутренний блок во входном манифесте k8s с помощью JQ (YQ) - PullRequest
1 голос
/ 11 марта 2019

У меня есть входной манифест kubernetes YAML, похожий на следующий:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    certmanager.k8s.io/acme-http01-edit-in-place: "true"
    certmanager.k8s.io/cluster-issuer: letsencrypt
  name: staging
  namespace: dev
spec:
  rules:
  - host: staging.domain.com
    http:
      paths:
      - backend:
          serviceName: task-11111
          servicePort: 80
        path: /task-11111/*
      - backend:
          serviceName: task-22222
          servicePort: 80
        path: /task-22222/*
      - backend:
          serviceName: task-33333
          servicePort: 80
        path: /task-33333/*
  tls:
  - hosts:
    - staging.domain.com
    secretName: staging-domain-com

Я пытаюсь добавить (если нет) или удалить (если есть) блок бэкэнда. Что у меня сейчас:

yq -y '.spec.rules[].http.paths += [{ "backend": { "serviceName": "'${CI_COMMIT_REF_NAME}'", "servicePort": 80}, "path": "/'${CI_COMMIT_REF_NAME}'/*"}]'

(добавляет новый блок со значением переменной, но не беспокоится, если он уже существует)

yq -y 'del(.. | .paths? // empty | .[] | select(.path |contains("'${CI_COMMIT_REF_NAME}'")) )'

(не с jq: error (at <stdin>:0): Invalid path expression with result {"backend":{"serviceName":...)

Таким образом, правила могут выглядеть следующим образом после удаления (предположим, что CI_COMMIT_REF_NAME = task-33333):

spec:
  rules:
  - host: staging.domain.com
    http:
      paths:
      - backend:
          serviceName: task-11111
          servicePort: 80
        path: /task-11111/*
      - backend:
          serviceName: task-22222
          servicePort: 80
        path: /task-22222/*

или подобное после добавления (предположим, что CI_COMMIT_REF_NAME = task-44444):

spec:
  rules:
  - host: staging.domain.com
    http:
      paths:
      - backend:
          serviceName: task-11111
          servicePort: 80
        path: /task-11111/*
      - backend:
          serviceName: task-22222
          servicePort: 80
        path: /task-22222/*
      - backend:
          serviceName: task-33333
          servicePort: 80
        path: /task-33333/*
      - backend:
          serviceName: task-44444
          servicePort: 80
        path: /task-44444/*

Любая помощь очень ценится.

1 Ответ

2 голосов
/ 11 марта 2019

[Следующее исправлено, чтобы отразить обновление вопроса.]

Предполагается, что CI_COMMIT_REF_NAME доступен для jq как $ CI_COMMIT_REF_NAME, что можно сделать с помощью jq с аргументом командной строки:

--arg CI_COMMIT_REF_NAME "$CI_COMMIT_REF_NAME"

соответствующий фильтр jq будет выглядеть следующим образом:

.spec.rules[0].http.paths |=
  (map(select(.path | index($CI_COMMIT_REF_NAME) | not)) as $new
   | if ($new | length) == length
     then . + [{ "backend": { "serviceName": $CI_COMMIT_REF_NAME, "servicePort": 80}, "path": ($CI_COMMIT_REF_NAME + "/*") }]
     else $new
     end )

Вы можете проверить это с помощью следующего вызова jq:

jq --arg CI_COMMIT_REF_NAME task-4444 -f program.jq input.json

где, конечно, input.json - это версия вашего YAML в формате JSON.

(я бы использовал index вместо contains, если это вообще возможно).

...