Ansible lineinfile не копирует последнюю строку на сервер
Я пытаюсь скопировать секретный файл настроек Python с сервера настроек в производственную среду. Поскольку настройки содержат пароли, я использую Ansible Vault.
Мой playbook выглядит так:
---
- hosts: production
tasks:
- include_vars: settings.yml
- name: Set properties
lineinfile:
dest: ~/temp/deploy
regexp: "{{ item.split('=')[0] }}\\s*="
line: "{{ item }}"
with_lines: echo "{{ config }}"
И мой settings.yml выглядит так:
config: |
ASD='DEF'
PROGRAM='PROG'
PASSWORD='MAGNUS123'
TEMP='TEST'
Однако, когда я запускаю playbook, я получаю файл:
ASD='DEF'
PROGRAM='PROG'
PASSWORD='MAGNUS123'
Хотя Ansible утверждает, что последняя строка также скопирована:
changed: [ssh.pythonanywhere.com] => (item=ASD='DEF' )
changed: [ssh.pythonanywhere.com] => (item=PROGRAM='PROG')
changed: [ssh.pythonanywhere.com] => (item=PASSWORD='MAGNUS123')
changed: [ssh.pythonanywhere.com] => (item=TEMP='TEST')
changed: [ssh.pythonanywhere.com] => (item=)
Что я делаю не так, чтобы вызвать это?
Ansible версия:
ansible --version
ansible 2.4.1.0
config file = None
ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
executable location = /usr/local/bin/ansible
python version = 3.6.2 (default, Jul 17 2017, 16:44:45) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)]
1 ответ
Вы делаете что-то совершенно ненужное (пропустите до конца), но давайте попробуем...
Что я делаю не так, чтобы вызвать это?
Если вы запустите следующее:
- shell: echo "{{ config }}" | hexdump
register: echo
- debug:
var: echo.stdout
Вы увидите, что вывод заканчивается на:
54 45 4d 50 3d 27 54 45 53 54 27 0a 0a
который TEMP='TEST'
сопровождаемый двумя символами новой строки. Когда используется в with_lines
цикл это вызовет две итерации - последняя с пустым значением, переданным item
,
Теперь подумайте, что происходит с вашими аргументами, когда item
пустой:
regexp
становится \\s*=
а также line
пустой.
Другими словами, вы указываете Ansible заменить строку, содержащую =
с пустой строкой.
Если отправной точкой является пустой файл, Ansible делает следующее:
- Добавляет
ASD='DEF'
линия. - Добавляет
PROGRAM='PROG'
линия. - Добавляет
PASSWORD='MAGNUS123'
линия. - Добавляет
TEMP='TEST'
линия. - Заменяет строку на
=
с пустой строкой (фактически это самая последняя строка).
И вот результат, который вы получите: три строки и одна пустая.
Вы также можете прийти к такому же выводу, просто используя debug
модуль для отображения значений "{{ item.split('=')[0] }}\\s*="
а также {{ item }}
который вы передаете lineinfile
аргументы.
echo
имеет -n
аргумент (" Не печатать завершающий символ новой строки "), но по причине, выходящей за рамки моего текущего понимания, он не меняет результат (проверьте с помощью hexdump
).
Однако если вы заменили echo
с printf
- свисающий 0x0a
там нет, и вы получите ожидаемый результат (уточните у hexdump
).
Все это, помимо того, что это хорошая головоломка, является еще одним аргументом против использования linefile
модуль в Ansible.
использование copy
(вы можете защитить весь файл с помощью Ansible Vault - см. decrypt
аргумент) или template
(вы можете иметь открытый шаблон и хранить значения переменных в защищенной от Vault форме). Определите желаемое состояние, не полагайтесь на текущее состояние. Период.