Сильные целочисленные переменные в 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
.