Есть ли итераторы и петли в марионетке?
Когда я определяю (?) ресурс, например. для обеспечения структуры dir, существуют ли какие-либо петли?
Вроде:
for X in [app1,app2] do:
file { '/opt/app/' + X:
ensure => directory,
owner => 'root',
group => 'root',
mode => '0644',
}
У меня есть десятки каталогов, и я действительно устал с объявлением его в марионетке. Это займет 15 LOC bash.
Любые идеи?
Ответы
Ответ 1
В марионеточном языке нет никаких циклов.
Но вы можете использовать массив вместо простой строки для заголовка и одновременно объявлять несколько ресурсов с теми же параметрами:
$b = '/opt/app'
file { [ "$b/app1", "$b/app2" ]:
ensure => directory,
owner => 'root',
group => 'root',
mode => 0644,
}
Вы также можете объявлять множество ресурсов одного и того же типа с разными параметрами, заканчивая каждый ресурс с помощью ;
, который немного компактнее, чем повторение file
и {
и }
s:
file {
[ "$b/app1", "$b/app2" ]:
ensure => directory,
owner => 'root',
group => 'root',
mode => 0755;
[ "$b/app1/secret", "$b/app2/secret" ]:
ensure => directory,
owner => 'root',
group => 'root',
mode => 0700;
}
В конкретном случае файлов вы можете настроить источник и использовать рекурсию:
file { "/opt/app":
source => "puppet:///appsmodule/appsdir",
recurse => true;
}
(для этого требуется наличие источника этой структуры каталогов для марионетки в качестве источника)
Вы можете определить новый тип ресурса, чтобы повторно использовать часть параметра несколько раз:
define foo {
file {
"/tmp/app/${title}":
ensure => directory,
owner => 'root',
mode => 0755;
"/tmp/otherapp/${title}":
ensure => link,
target => "/tmp/app/${title}",
require => File["/tmp/app/${title}"]
}
}
foo { ["app1", "app2", "app3", "app4"]: }
Начиная с Puppet 2.6, имеется доступная Ruby DSL, которая имеет все возможности циклирования, которые вы могли бы запросить: http://www.puppetlabs.com/blog/ruby-dsl/ (я однако не использовал его). В Puppet 3.2 они ввели несколько экспериментальных циклов однако эти функции могут измениться или исчезнуть в последующих выпусках.
Ответ 2
Начиная с версии 3.2, lambdas
Вы должны установить parser = future
в puppet.conf.
$a = [1,2,3]
each($a) |$value| { notice $value }
Другим вариантом для объявления нескольких определенных типов является create_resources. Передайте хэш хэшей:
create_resources(file, {
'/tmp/test1' => {
ensure => directory,
owner => 'root',
group => 'root',
mode => '0644',
},
'/tmp/test2' => {
ensure => directory,
owner => 'www-data',
group => 'www-data',
mode => '0755',
},
})
Ответ 3
Как и в Puppet 4 (и "будущий парсер" поздних версий Puppet 3), кукольный DSL имеет итерационные функции, похожие по форме и функции, на некоторые из методов массивов Ruby и хэшей:
- each - оценивает блок кода (формально, лямбда) для каждого элемента массива или хэша
- filter - применяет лямбда к каждому элементу массива или хешу и возвращает массив или хэш из тех, для которых вычисляется лямбда к true
- map - применяет лямбда к каждому элементу массива или хешу и возвращает массив результатов
- reduce - применяет лямбда к каждому элементу массива или хешу, чтобы создать один результат, который он возвращает
Нет индексированного цикла for
вдоль линий C или Java, но вы можете объединить секцию массива с любой из вышеперечисленных функций для достижения итерации над подмножеством структуры данных. Не существует неопределенной итерации по линиям цикла C или Java while
.
Конечно, вы все равно можете использовать ориентированные на ресурсы подходы, описанные в других ответах, и иногда один из них действительно лучший доступный подход. Однако вы больше не можете использовать Ruby DSL; он полностью удаляется из Кукольного 4. Среди итерационных функций способность определять пользовательские функции, вознесение ориентированных на данные подходов в пользу и все исторические стандартные функции Puppet, Ruby DSL, кажется, не так сильно пропущены.
Ответ 4
Да. "Ruby DSL" может помочь, просто используйте расширение файла ".rb" вместо ".pp" в манифесте, и вы можете определить кукольный "тип" следующим образом:
define 'myapps::structure', :applist do
@applist.each do |app|
file( @name+'/'+app,
:ensure => directory,
:owner => 'root',
:group => 'root',
:mode => '0644')
end
end
Классы и узлы также могут быть определены аналогичным образом. Обратите внимание, что эта функция устарела со времени выпуска 3