Сильные целочисленные переменные в YAML

Я использую Ansible для развертывания webapp. Я бы хотел дождаться запуска приложения, установив, что данная страница возвращает JSON с заданным ключом/значением.

Я хочу, чтобы задача была проверена несколько раз перед сбоем. Поэтому я использую комбинацию until/retries/delay keybwords.

Проблема в том, что я хочу, чтобы количество retries было взято из переменной. Если я напишу:

  retries: {{apache_test_retries}}

Я попадаю в обычный Ямл Гоча (http://docs.ansible.com/YAMLSyntax.html#gotchas).

Если вместо этого я пишу:

  retries: "{{apache_test_retries}}"

Я говорю, что значение не является целым числом.

ValueError: неверный литерал для int() с базой 10: '{{apache_test_retries}}'

Вот мой полный код:

- name: Wait for the application to be running
  local_action:
    uri
    url=http://{{webapp_url}}/health
    timeout=60
  register: res
  sudo: false
  when: updated.changed and apache_test_url is defined
  until: res.status == 200 and res['json'] is defined and res['json']['status'] == 'UP'
  retries: "{{apache_test_retries}}"
  delay: 1

Любая идея о том, как обойти эту проблему? Благодарю.

Ответ 1

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

Решение Daniels действительно должно работать:

retries: "{{ apache_test_retries | int }}"

Но если вы используете небольшую более старую версию, это не сработает. Поэтому убедитесь, что вы обновили I, проверенный на 1.8.4, и он работает, и он не работает на 1.8.2

Это была оригинальная ошибка на доступной: https://github.com/ansible/ansible/issues/5865

Ответ 2

Вы должны иметь возможность преобразовать его в целое число с int-фильтром:

retries: "{{ apache_test_retries | int }}"

Ответ 3

Вы проверили, что у вас есть правильное имя переменной?

Ansible использует шаблон переменной Jinja2. Поэтому, если переменная не существует, она заменяет ее пустой строкой.

http://jinja.pocoo.org/docs/dev/templates/

Если переменная или атрибут не существует, вы получите неопределенное значение. То, что вы можете сделать с такой стоимостью, зависит от конфигурации приложения: поведение по умолчанию заключается в том, что он оценивает пустую строку, если печатается, и что вы можете перебирать ее, но каждая другая операция завершается с ошибкой.

Ответ 4

Я столкнулся с подобной проблемой, в моем случае я хотел перезапустить службу celeryd. Для перезагрузки иногда требуется очень много времени, и я хотел бы дать ему максимум 30 секунд для плавного перезапуска, а затем принудительно перезапустить его. Я использовал async для этого (опрос для повторного запуска каждые 5 секунд).

celery/handlers/main.yml

- name: restart celeryd
  service:
    name=celeryd
    state=restarted
  register: celeryd_restart_result
  ignore_errors: true
  async: "{{ async_val | default(30) }}"
  poll: 5

- name: check celeryd restart result and force restart if needed
  shell: service celeryd kill && service celeryd start
  when: celeryd_restart_result|failed

И затем я использую выше в playbook как обработчики для задачи (restart celeryd всегда первый в списке notify)


В вашем случае возможно что-то вроде ниже. Не проверял, делает ли это, но может дать вам некоторую взломанную идею решить ее по-другому. Кроме того, поскольку вы будете игнорировать ошибки в 1-й задаче, вам нужно убедиться, что все в порядке:

- name: Poll to check if the application is running
  local_action:
    uri
    url=http://{{webapp_url}}/health
    timeout=60
  register: res
  sudo: false
  when: updated.changed and apache_test_url is defined
  failed_when: res.status != 200 and res['json'] is not defined and not res['json']['status'] == 'UP'
  ignore_errors: true
  async: "{{ apache_test_retries | default(60) }}"
  poll: 1

  # Task above will exit as early as possible on success
  # It will keep trying for 60 secs, polling every 1 sec
  # You need to make sure it fine **again** because it has ignore_errors: true

- name: Final UP check
  local_action:
    uri
    url=http://{{webapp_url}}/health
    timeout=60
  register: res
  sudo: false
  when: updated.changed and apache_test_url is defined
  failed_when: res.status != 200 and res['json'] is not defined and not res['json']['status'] == 'UP'

Надеюсь, это поможет вам решить проблему с ошибкой в retries.