В моей конфигурации Puppet я хочу сказать: «Если я объявлю класс X, примените его ресурсы до класса Y». Другими словами, я хочу объявить упорядочивание, но промолчу о том, применять ли класс X или нет.
Если я правильно понимаю метапараметр «до», говоря:
class X {
...
before => Class['Y'],
}
class Y {
...
}
node N {
include Y
}
node M {
include X
include Y
}
будет включать ресурсы X и Y на обоих узлах M и N. Вместо этого я хочу выразить отдельно: «Применить только Y» или «Применить X и Y и применить X перед Y».
Для контекста, что я хочу сделать более конкретно, это убедиться, что мои репозитории Yum настроены до того, как Puppet применит ресурсы пакета. Я хочу убрать некоторые репозитории с некоторых узлов. Я хочу, чтобы определения ресурсов моего пакета оставались наивными в отношении соответствующих репозиториев; Я не хочу засорять определения ресурсов своего пакета зависимостями от конкретных репозиториев.
Я пробовал использовать этапы выполнения, но, помимо самой простой конфигурации, они, похоже, вызывают циклы зависимости. Например, это сработает:
stage { 'first': before => Stage['main'] }
class X {
...
before => Class['Y'],
}
class Y {
...
}
node N {
include Y
}
node M {
class { "X": stage => first }
include Y
}
Но этого не было бы:
stage { 'first': before => Stage['main'] }
class X {
...
class { "Z": stage => first } # to avoid Z "floating off"
before => Class['Y'],
}
class Y {
...
include Z
}
class Z { ... }
node N {
include Y
}
node M {
class { "X": stage => first }
include Y
}
Во втором случае Puppet считает, что существует цикл зависимости. Я предполагаю, что это связано с объявлением Z и управлением его ресурсами на двух разных этапах. Я мог бы потенциально упростить нужные мне классы на этапе «сначала», чтобы избежать проблем цикла зависимости, которые я вижу на практике, но документация Puppet распространяется FUD об этапах выполнения.
Вот конкретная настройка, которая делает этапы выполнения для меня действительно непривлекательными. В виртуальных машинах разработки я загружаю сервер Yum локально через devrepo.
class yum::devrepo {
# Ensures httpd is running as a Yum server before anything else
# tries to install packages from it.
exec { 'httpd-for-yum':
command => '/sbin/service httpd restart',
require => Class['yum::server'],
}
yumrepo {
"devrepo":
require => [Exec['httpd-for-yum'],],
descr => "Local Dev YUM Repo",
baseurl => "http://localhost/repos/redhat/5/x86_64/",
gpgcheck => "0",
enabled => "1",
}
}
class yum::server {
include httpd
package { ['createrepo']:
ensure => present;
}
exec { 'update-repo-metadata':
require => [ Package['createrepo']],
cwd => '/var/www/html/yum',
command => '/usr/bin/createrepo --update -d repos/redhat/5/x86_64/',
creates => '/var/www/html/yum/repos/redhat/5/x86_64/repodata/repomd.xml',
}
file {'/etc/httpd/conf.d/yum.conf':
ensure => file,
mode => 0644,
source => "puppet:///modules/yum/yum_httpd.conf",
require => Package['httpd'],
notify => Service['httpd'],
}
}
Я хочу включить репозиторий Yum на некоторые узлы и репозиторий разработчиков на другие.
Если я положу yum::server
и yum::devrepo
на этапе «сначала», а затем более поздние объявления httpd в других классах позже вызывают проблемы, потому что другие классы помещают httpd в основной этап.
Если Puppet может выразить «Если я объявлю класс X, примените его ресурсы до класса Y», как? Если нет, как мне получить желаемый порядок без циклов зависимости и без включения ресурсов репозитория Yum, которые я хочу опустить?
Не уверен, что это сработает, но, возможно, вы могли бы попытаться определить зависимости в области уровня узла. Например:
class X {
...
}
class Y {
...
}
node N {
include Y
}
node M {
Class['X'] -> Class['Y']
include X
include Y
}
Это выглядит как ответ Голи может работать. Вот образец, который я на себе нанес. Вроде пока работает.
class yum::reposareready {
# The sole and critical purpose of this class is to act as an
# intermediary between various repositories and the package
# resources. It lets us do things like:
# class yum::repofoo { ... }
# class applicationbar {
# package { 'bazfromtherightrepo': ..., require => yum::reposareready, }
# }
# node n {
# class { 'yum::repofoo': before => Class['yum::reposareready'] }
# }
# With this pattern:
# 1. The repository resource doesn't need to know about its ordering.
# 2. Nodes can mix in repository resources, including and excluding
# repositories as needed.
# 3. Classes that declare package resources need only require a
# generic "repos are ready" class rather than the knowing the
# specific repository from which to get a package.
# DO NOT DO THIS:
# class yum::repofoo { before => Class['yum::reposareready'] }
# class yum::repobar { before => Class['yum::reposareready'] }
#
# node n {
# include yum::repofoo
# }
#
# node m {
# include yum::repobar
# }
# The former scopes the ordering dependency to the node, whereas the
# latter does not. The latter would make Puppet apply yum::repofoo
# to both nodes n and m, whereas the former only applies
# yum::repofoo to node n.
}