У меня есть определенный тип ресурса, чтобы добавить строку в файл, если он не существует, как показано ниже:
define appendLineToFile($file, $line, $user) {
exec { "echo \"\\n$line\" >> \"$file\"":
path => '/bin',
unless => "grep -Fx \"$line\" \"$file\"",
user => $user,
}
}
Он отлично работает большую часть времени, но не в ситуациях, подобных приведенной ниже, где у вас есть двойные кавычки, которые нужно экранировать дважды (что ужасно сбивает с толку):
appendLineToFile { 'Add http_proxy & https_proxy to sudoers':
file => '/etc/sudoers',
line => "Defaults env_keep += \\\"http_proxy https_proxy\\\"",
user => root,
}
Есть ли способ изменить определенный тип ресурса, который не требует экранирования как такового? например
line => "Defaults env_keep += \"http_proxy https_proxy\"",
Разнорабочий5 предложил использовать Авгий. Вот пример того, как это можно сделать:
Если вы хотите, чтобы обе записи были в одной строке, используя +=
, вы можете использовать Augeas следующим образом:
augeas { "Add http_proxy & https_proxy to sudoers":
context => "/files/etc/sudoers",
# Only if no node exists for http_proxy
onlyif => "match Defaults/env_keep/var[. = 'http_proxy'] size==0",
changes => [
# Create a new Defaults line for the two variables
"ins Defaults after Defaults[last()]",
# Make this Defaults line a += type
"clear Defaults[last()]/env_keep/append",
# assign values to the two variables
"set Defaults[last()]/env_keep/var[1] http_proxy",
"set Defaults[last()]/env_keep/var[2] https_proxy",
],
}
Однако вы можете захотеть избежать корреляции двух переменных, чтобы она все равно работала, если одна переменная уже установлена. В этом случае я бы разделил проблему на две части, создав новый узел Defaults только для http_proxy и повторно используя его (с зависимостью) для https_proxy.
Две вещи:
Puppet хорошо интегрируется с инструментом под названием Авгий:
Augeas - прекрасный инструмент, который обрабатывает файлы конфигурации (ну, на самом деле что угодно, но в основном это файлы конфигурации) как деревья значений. Затем вы изменяете дерево по своему усмотрению и записываете файл обратно.
Для файлов, которые понимает Augeas, очень легко вносить программные изменения, не беспокоясь о комментариях, пробелах, синтаксическом анализе или любых других важных деталях. Также Авгий поддерживает формат файла sudoers.
По состоянию на судо версия 1.7.2, он поддерживает includedir
директива, которая позволяет указать каталог для расширения sudoers. Файлы в этом каталоге должны содержать фрагменты действительного кода sudoers, и sudo будет читать и использовать их точно так же, как если бы они были включены в исходный файл. Я использую это в Puppet с настраиваемым ресурсом:
define sudo-include( content ) {
file { "/etc/sudoers.d/$name":
content => $content,
mode => 0440,
user => root,
group => root,
}
}
[...]
sudo-include { "moreusers":
content => "\
joe ALL=(ALL) ALL
mike ALL=(ALL) NOPASSWD:ALL
"
}
Когда вы используете sudo-include
ресурс, он автоматически создает файл в нужном месте с нужными разрешениями, и все, что вам нужно сделать, это дать ему имя и содержимое.
Если вы не используете Debian Squeeze, который использует тире вместо bash в качестве оболочки по умолчанию, вы можете использовать одинарные кавычки для параметра, чтобы echo
, и используйте -e
, что позволяет использовать ограниченное количество escape-символов.
См. Также Общие модули как минимум для двух реализаций того, что вы делаете.