У меня есть файл Ansible YAML, отформатированный, как показано ниже. Обратите внимание на части - name
и - when
.
- name: populate package facts
package_facts:
- name: install auditd
apt:
name: auditd
state: present
register: apt_status
until: apt_status is success
retries: 12
delay: 10
- name: touch stig.rules
file:
path: /etc/audit/rules.d/stig.rules
state: touch
mode: '0640'
modification_time: preserve
access_time: preserve
# R-238197 UBTU-20-010002
- name: stigrule_238197__etc_gdm3_greeter_dconf_defaults_enable
ini_file:
path: /etc/gdm3/greeter.dconf-defaults
section: org/gnome/login-screen
option: banner-message-enable
value: "{{ ubuntu2004STIG_stigrule_238197__etc_gdm3_greeter_dconf_defaults_enable_Value }}"
no_extra_spaces: yes
notify: dconf_update
when:
- ubuntu2004STIG_stigrule_238197_Manage
- "'gdm3' in packages"
Я обрабатываю его и удаляю некоторые элементы, а затем выгружаю в файл, используя метод ниже:
def dump(path: str, export: list) -> None:
yaml: YAML = YAML()
yaml.default_flow_style = False
yaml.preserve_quotes = True
yaml.width = 4096 # Prevent line breaks
yaml.indent(mapping=2, sequence=2, offset=0) # Default values
with open(path, "w", encoding=ENCODING) as fp:
yaml.dump(export, fp)
С отступом по умолчанию результат будет таким, как показано ниже:
- name: populate package facts
package_facts:
- name: install auditd
apt:
name: auditd
state: present
register: apt_status
until: apt_status is success
retries: 12
delay: 10
- name: touch stig.rules
file:
path: /etc/audit/rules.d/stig.rules
state: touch
mode: '0640'
modification_time: preserve
access_time: preserve
# R-238197 UBTU-20-010002
- name: stigrule_238197__etc_gdm3_greeter_dconf_defaults_enable
ini_file:
path: /etc/gdm3/greeter.dconf-defaults
section: org/gnome/login-screen
option: banner-message-enable
value: "{{ ubuntu2004STIG_stigrule_238197__etc_gdm3_greeter_dconf_defaults_enable_Value }}"
no_extra_spaces: yes
notify: dconf_update
when:
- ubuntu2004STIG_stigrule_238197_Manage
- "'gdm3' in packages"
Как видите, файл Ansible уже представляет собой список элементов, начиная со смещения 0. Затем элементы списка после - when
также будут использовать это значение смещения 0. Как я могу сохранить исходный отступ - смещение 0 для - name
, но смещение 2 для всех остальных?
С ruamel.yaml у вас может быть только один отступ для всех сопоставлений и один для всех последовательностей.
Если вы хотите сохранить несоответствие, вам нужно сделать отступ 4 и смещение 2 и удалить дополнительные два пробела, которые начинаются с каждой строки (эффективно уменьшая последовательности корневого уровня):
import sys
import ruamel.yaml
YAML = ruamel.yaml.YAML
from pathlib import Path
def dump(path: str, export: list) -> None:
def strip_first_two(s):
res = []
for x in s.splitlines(True):
xl = x.lstrip()
# do not dedent full comment lines
if xl and xl[0] == '#' or not x.startswith(' '):
res.append(x)
else:
res.append(x[2:])
return ''.join(res)
yaml: YAML = YAML()
yaml.default_flow_style = False # default
yaml.width = 4096 # Prevent line breaks
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.dump(export, Path(path), transform=strip_first_two)
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(Path('input.yaml'))
dump('output.yaml', data)
print(Path('output.yaml').read_text())
который дает:
- name: populate package facts
package_facts:
- name: install auditd
apt:
name: auditd
state: present
register: apt_status
until: apt_status is success
retries: 12
delay: 10
- name: touch stig.rules
file:
path: /etc/audit/rules.d/stig.rules
state: touch
mode: '0640'
modification_time: preserve
access_time: preserve
# R-238197 UBTU-20-010002
- name: stigrule_238197__etc_gdm3_greeter_dconf_defaults_enable
ini_file:
path: /etc/gdm3/greeter.dconf-defaults
section: org/gnome/login-screen
option: banner-message-enable
value: "{{ ubuntu2004STIG_stigrule_238197__etc_gdm3_greeter_dconf_defaults_enable_Value }}"
no_extra_spaces: yes
notify: dconf_update
when:
- ubuntu2004STIG_stigrule_238197_Manage
- "'gdm3' in packages"
Если у вас есть какие-либо комментарии в конце строки, они сдвинутся на две позиции влево.
Если у вас нет многострочных скаляров со встроенными маркерами комментариев, вы можете легко обрабатывать
это в strip_first_two
, заменив ' #'
на ' #'
в каждой строке. Если у вас есть оба, это не так тривиально
и вам придется пройтись по структуре данных перед дампом и настроить каждый начальный столбец каждого комментария EOL.
Установка yaml.default_flow_style = False
необязательна, так как это значение по умолчанию для кругового дампа (с другой стороны, явное
лучше неявного). Но вы не должны устанавливать yaml.preserve_quotes
для экземпляра YAML
в вашей функции dump
, поскольку это только
работает во время загрузки документа YAML, так что это может ввести кого-то в заблуждение.
Я также склонен использовать экземпляры pathlib.Path
и позволять ruamel.yaml
делать правильные вещи в отношении кодирования и открытия ('w' против 'wb').
Мне просто нужно добавить еще один комментарий. Так как я пытаюсь свести разницу к минимуму, необходимо yaml.preserve_quotes
. В противном случае одинарные кавычки могут быть преобразованы в двойные кавычки во время дампа, даже если они используются при загрузке. Итак, в моем случае это необходимо как при чтении, так и при дампе.
Спасибо за подробную информацию. Вы добавили больше предложений, чем было задано, и я действительно ценю это.