“Не удалось получить содержимое файла” при попытке подать ansible playbook из stdin

Вопрос или проблема

Я хотел передать плейбук в ansible-playbook 2.4.2.0 из stdin на RHEL 7.5. Я нашел этот пост, который казался многообещающим, но у меня не работает:

$ cat  ~/simple-ansible-playbook.yaml | ansible-playbook -i ~/inventory.yaml /dev/stdin
ERROR! Не удается получить содержимое файла
Не удалось найти или получить доступ к '/dev/stdin'
$

Я отслеживал сообщение до /usr/lib/python2.7/site-packages/ansible/parsing/dataloader.py:

    if not self.path_exists(b_file_name) or not self.is_file(b_file_name):
        raise AnsibleFileNotFound("Не удается получить содержимое файла", file_name=file_name)

os.path.isfile() возвращает False для /dev/stdin, который является символьной ссылкой на специальный файл:

$ ls -l /dev/stdin
lrwxrwxrwx. 1 root root 15 Nov 11 13:11 /dev/stdin -> /proc/self/fd/0
$ ls -Ll /dev/stdin
crw--w----. 1 stack tty 136, 3 Feb 15 07:45 /dev/stdin

Кто-нибудь имеет идеи, как это заставить работать? Я не понимаю, почему это, казалось, работало для указанного поста, но у меня не получается.

Обновление

Я думаю, я лучше это понимаю. Исходный пост использовал here document, который оболочка, очевидно, возвращает в обычный файл. В моем методе данные находятся в канале. Я не осознавал, что оболочка ведет себя по-другому в этом отношении: я полагал, что here document также приведет к каналу. Так что, по крайней мере, я узнал что-то новое о разнице, но, похоже, я не могу сделать то, что я хочу, если только ansible-playbook не изменится.

Я понял, что мне придется взять себя в руки и поместить плейбук во временный обычный файл, а не передавать его через stdin.

Исходный пост использовал here document, который оболочка, очевидно, возвращает в обычный файл

Версия с каналом работает прекрасно на современной версии ansible (я просто использовал heredoc, чтобы сделать ответ более кратким):

$ printf -- '- hosts: all\n  tasks:\n    - debug: msg=hello\n' | \
      ansible-playbook -c local -i localhost, /dev/stdin

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] =>
  msg: hello

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

$ ls -l /dev/stdin
lrwxrwxrwx 1 root root 15 Feb 15 16:44 /dev/stdin -> /proc/self/fd/0

$ ansible --version
ansible 2.7.7
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 2.7.15rc1 (default, Nov 12 2018, 14:31:15) [GCC 7.3.0]

Итак, решение вашей проблемы – обновиться до современной версии ansible.

Тем не менее, я не хотел, чтобы все было мрачно, поэтому существует обходной путь, если вы настаиваете на передаче данных в ansible через канал: обманите и сериализуйте поток в файл с помощью tee:

$ printf -- '- hosts: all\n  tasks:\n    - debug: msg=hello\n' | \
      tee being-on-old-software-is-dangerous.yml | \
      ansible-playbook -c local -i localhost, being-on-old-software-is-dangerous.yml

Ответ или решение

Решение проблемы: "Не удается получить содержимое файла" при попытке передачи playbook в ansible-playbook через stdin

Ошибка "Unable to retrieve file contents" возникает при использовании более старой версии Ansible (в вашем случае 2.4.2.0), когда вы пытаетесь передать playbook через стандартный ввод. Решение данной проблемы требует понимания того, как Ansible обрабатывает входные данные и использование правильного подхода.

Причина проблемы

Как вы правильно заметили, Ansible в версии 2.4.2.0 не поддерживает обработку входных данных через /dev/stdin. При выполнении команды Ansible проверяет, существует ли файл, передаваемый в качестве аргумента, и на самом деле /dev/stdin не является обычным файлом, а представляет собой специальный файл (символическую ссылку) на текущий дескриптор файла. Это вызывает сбой в функции проверки существования файла, что приводит к ошибке.

Сравнение с более новыми версиями Ansible

Новые версии Ansible, такие как 2.7.x и выше, обрабатывают этот сценарий корректно. Вы можете передавать playbook через конвейер, и Ansible сможет прочитать его из стандартного ввода без проблем.

Пример работы с новым Ansible:
$ printf -- '- hosts: all\n  tasks:\n    - debug: msg=hello\n' | ansible-playbook -c local -i localhost, /dev/stdin

Решение для старой версии Ansible

Если вы не можете обновить Ansible, существуют обходные пути:

  1. Использование временного файла: Вы можете создать временный файл и записать в него содержимое вашего playbook, после чего передать его в ansible-playbook. Например:

    $ cat ~/simple-ansible-playbook.yaml > /tmp/temp_playbook.yaml && ansible-playbook -i ~/inventory.yaml /tmp/temp_playbook.yaml
  2. Использование утилиты tee: Если вы хотите оставаться в рамках цепочек команд, можно использовать tee для создания временного файла в рамках командной цепочки:

    $ printf -- '- hosts: all\n  tasks:\n    - debug: msg=hello\n' | tee /tmp/playbook.yml | ansible-playbook -i localhost, /tmp/playbook.yml

Важность обновления

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

Заключение

Хотя использование stdin оказывается невозможным с Ansible 2.4.2.0, существуют простые обходные пути, такие как создание временных файлов или использование утилиты tee. Тем не менее, лучшим решением будет обновление вашего Ansible до более новой версии, что предотвратит возникновение подобных проблем в будущем и обеспечит доступ к улучшенным возможностям платформы.

Оцените материал
Добавить комментарий

Капча загружается...