Несколько json_query в Ansible? - PullRequest
0 голосов
/ 05 мая 2020

У меня есть следующий файл yaml.

resources:
  - apiVersion: v1
    kind: Deployment
    metadata:
      labels:
        app: test
      name: test-cluster-operator
      namespace: destiny001
    spec:
      selector:
        matchLabels:
          name: test-cluster-operator
          test.io/kind: cluster-operator
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            name: test-cluster-operator
            test.io/kind: cluster-operator
        spec:
          containers:
          - args:
            - /path/test/bin/cluster_operator_run.sh
            env:
            - name: MY_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            imagePullPolicy: IfNotPresent
            livenessProbe:
              failureThreshold: 3
              httpGet:
                path: /healthy
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 10
              periodSeconds: 30
              successThreshold: 1
              timeoutSeconds: 1
            name: test-cluster-operator
            readinessProbe:
              failureThreshold: 3
              httpGet:
                path: /ready
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 10
              periodSeconds: 30
              successThreshold: 1
              timeoutSeconds: 1
            resources:
              limits:
                cpu: '1'
                memory: 256Mi
              requests:
                cpu: 200m
                memory: 256Mi
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /var/data
              name: data-cluster-operator
          dnsPolicy: ClusterFirst
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext: {}
          serviceAccount: test-cluster-operator
          serviceAccountName: test-cluster-operator
          terminationGracePeriodSeconds: 30
          volumes:
          - name: data-cluster-operator
            persistentVolumeClaim:
              claimName: data-cluster-operator

Я пытаюсь получить значение переменной env с именем MY_NAMESPACE. Это то, что я пробовал в Ansible, чтобы добраться до пути к дереву env.

- name: "set test fact"
  set_fact:
    myresult: "{{ yaml_file_variable | json_query(\"resources[?metadata.name=='test-cluster-operator'].spec.template.spec\") | json_query(\"containers[?name=='test-cluster-operator'].env\") }}"

- name: "debug"
  debug:
    msg: "{{ myresult }}"

Это создает пустой список, однако первый json_query работает хорошо.

Как использовать json_query правильно в этом случае? Могу ли я добиться этого с помощью всего одного json_query?

EDIT: Кажется, я ближе к решению, но результат - это список, а не строка, что меня раздражает.

- name: "set test fact"
  set_fact:
    myresult: "{{ yaml_file_variable | json_query(\"resources[?metadata.name=='test-cluster-operator'].spec.template.spec\") | json_query(\"[].containers[?name=='test-cluster-operator']\") | json_query(\"[].env[?name=='MY_NAMESPACE'].name\") }}"

Это печатает - - MY_NAMESPACE вместо MY_NAMESPACE.

Должен ли я использовать фильтр first каждый раз после json_query? Я точно знаю, что есть только один элемент containers. Я не понимаю, почему json_query возвращает список.

Это, наконец, работает, но я не знаю, правильный ли это способ сделать это.

- name: "set test fact"
  set_fact:
    myresult: "{{ yaml_file_variable | json_query(\"resources[?metadata.name=='test-cluster-operator'].spec.template.spec\") | first | json_query(\"containers[?name=='test-cluster-operator']\") | first | json_query(\"env[?name=='MY_NAMESPACE'].valueFrom \") | first }}"

1 Ответ

1 голос
/ 05 мая 2020

json_query использует jmespath, а jmespath всегда возвращает список. Вот почему ваш первый пример не работает. Первый запрос возвращает список, а второй пытается запросить ключ. Вы исправили это во втором с помощью [].

Вам также не хватает выражения канала jmespath: |, которое используется в значительной степени, как и следовало ожидать - результат первого запроса может быть передан по конвейеру в новый. Обратите внимание, что он отличается от фильтров ansible, использующих тот же символ.

Этот запрос:

resources[?metadata.name=='test-cluster-operator'].spec.template.spec | [].containers[?name=='test-cluster-operator'][].env[].valueFrom

Должен дать вам следующий результат:

[
  {
    "fieldRef": {
      "apiVersion": "v1",
      "fieldPath": "metadata.namespace"
    }
  }
]

Ваш задача должна выглядеть так:

- name: "set test fact"
  set_fact:
    myresult: "{{ yaml_file_variable | json_query(\"resources[?metadata.name=='test-cluster-operator'].spec.template.spec | [].containers[?name=='test-cluster-operator'][].env[].valueFrom\") | first }}"

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

...