Назад | Перейти на главную страницу

Как я могу сказать Puppet: «Если я объявлю класс X, примените его ресурсы до класса Y»?

В моей конфигурации 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.

}