Ansible - работа с неожиданным STDOUT в пользовательском модуле - PullRequest
0 голосов
/ 24 января 2020

Я написал пользовательский модуль, который упаковывает библиотеку Python. Я определяю result dict следующим образом:

result = dict(
    changed=False,
    original_message='Running DBSCONTROL',
    message=''
)

Позже в коде я заключаю вызов библиотеки в try/except следующим образом:

try:
    dbsc = DbsControl(
        module.params.get('user'),
        module.params.get('host'),
        module.params.get('script')
    )
    dbsc.runme()
    result['message'] = 'DBSCONTROL_SUCCESSFULL'
    module.exit_json(**result)
except Exception as ex:
    result['message'] = str(ex)
    module.fail_json(msg='Failed DBSCONTROL execution', **result)

У меня нет ни одного print оператор в любом месте модуля, и моя библиотека выводит журнал в файл.

Наконец, я называю эту Ansible роль

- name: Run dbscontrol utility
  dbscontrol:
    user: "{{ hostvars[groups['dbs_server'][0]]['ansible_user'] }}"
    host: "{{ groups['dbs_server'][0] }}"
    script: "dbscontrol_config.yml"
  register: result
- debug:
    msg: "{{ result }}"

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

MSG:

MODULE FAILURE
See stdout/stderr for the exact error

Как ни странно, я вижу result, встроенный в раздел MODULE_STDOUT вывода. Фактически это последний раздел перед началом MODULE_STDERR

И MODULE_STDOUT, и MODULE_STDERR состоят из идентичных сообщений журнала из библиотеки с единственным отличием result строк:

2020-01-23 13:40:52,070 - ttautils.dbscontrol - INFO - DBS control run is complete, exiting

{"changed": false, "original_message": "Running DBSCONTROL", "message": "DBSCONTROL_SUCCESSFULL", 
    "invocation": {"module_args": {"user": "root", "host": "fiesta1.td.teradata.com", "script": 
    "dbscontrol_config.yml", "dbc_user": "dbc", "dbc_pwd": "dbc", "logfile": "dbscntl_2020-01-23-13-38-15.log",  
    "loglevel": "DEBUG", "validate": "False", "config": "user_config/common", "locale": "TPG_6700C", 
    "timeout": "7200", "disable_local_overrides": false, "params": "user_config/user.yml"}}, 
    "warnings": ["The value False (type bool) in a string field was converted to 'False' (type string). 
        If this does not look like what you expect, quote the entire value to ensure it does not change."]}

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

2 дня спустя

Хорошо, теперь я знаю проблему , Это связано с библиотекой, которую я оборачиваю, записывая вывод в STDOUT / STDERR, так как он использует подпроцесс для внутреннего использования. Когда Ansible пытается проанализировать STDOUT, в этом методе происходит сбой из-за всех дополнительных не JSON выходных данных в STDOUT. Как бороться с этой ситуацией? Как я могу гарантировать, что мой пользовательский модуль имеет первичный STDOUT с выводом в формате JSON? Я пытался сделать sys.stdout.flush() безрезультатно.

Это практически делает написание пользовательского модуля бесполезным. Пожалуйста, Ansible Гуру, есть намеки?

1 Ответ

0 голосов
/ 28 января 2020

Таким образом, ответ на эту проблему прост: когда вы звоните exit_json или fail_json, вы не можете получить sys.stdout с каким-либо выводом. Причина также проста: после запуска вашего кода результат обрабатывается этим Ansible кодом . Который анализирует res.get('stdout', u'') и, если есть какие-либо ошибки синтаксического анализа, вы получаете тот массивный дамп STDOUT, о котором я упоминал в своем вопросе.

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

...