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

Puppet: как переопределить / переопределить вне дочернего класса (подробный пример использования и пример)

Вариант использования, который я пытаюсь проиллюстрировать, - это когда объявлять какой-либо элемент (службу eq mysqld) с конфигурацией по умолчанию, которая может быть включена на каждый узел (разделение классов в примере для базового узла), и при этом иметь возможность переопределить этот же элемент в некоторый конкретный класс (например, mysql :: server), который должен быть включен конкретными узлами (например, myserver.local)

Я проиллюстрировал этот вариант использования приведенным ниже примером, где я хочу отключить службу mysql на всех узлах, но активировать ее на определенном узле. Но, конечно, анализ Puppet не выполняется, потому что служба [mysql] включается дважды. И, конечно же, класс mysql :: server не имеет отношения к дочернему классу stripdown.

Есть ли способ переопределить Сервис ["mysql"], или пометить его как основной, или что-то еще? Я думал о виртуальных элементах и ​​функции реализации, но она позволяет применять элемент только несколько раз, а не переопределять или отменять.

# In stripdown.pp :
class stripdown {
    service {"mysql": enable => "false", ensure => "stopped" }
}

# In mysql.pp :
class mysql::server {  
    service { mysqld:  
        enable      => true,  
        ensure      => running,  
        hasrestart  => true,  
        hasstatus   => true,  
        path        => "/etc/init.d/mysql",  
        require     => Package["mysql-server"],  
    }
}

# Then nodes in nodes.pp :
node basenode {
    include stripdown
}

node myserver.local inherits basenode {  
    include mysql::server`         # BOOM, fails here because of Service["mysql"] redefinition             
}

Всякий раз, когда вы обнаруживаете, что говорите: «Я хочу, чтобы этот компонент вел себя одним способом в одном узле, но другим - в другом узле», вам, вероятно, придется смотреть на определение, управляемое переменными, либо через условные выражения в определении класса, либо через подстановки. в шаблоне.

К сожалению, ваш пример показывает, что вы пытаетесь использовать наследование, которое довольно сильно нарушено в марионетке и причинит вам много огорчений, потому что одна из вещей, которые он нарушает, - это переопределение переменных в узлах.

ОБНОВЛЕНИЕ: старые детали ответа устарели

Что я делаю начиная с версии 2.7, так это то, что все переменные, используемые классом, вообще не являются глобальными переменными, а являются параметрами с разумными значениями по умолчанию. Вы по-прежнему не хотите использовать наследование, встроенное в Puppet, но теперь вы можете переопределить определенные переменные непосредственно из определения узла, и вы даже можете иметь примитивную форму наследования вручную, если один класс принимает переменные, а затем передает их вызову другой класс. Например, в определениях ваших узлов должны быть:


node experimental_server {
  # This will still call class 'databases', but will install Postgresql and not Mysql
  # as a default.  You can still override it the same way as with 'databases'
  class { 'mydept::nextgeneration': },
}
node server_with_mysql {
  class { 'databases':
    mysql_enabled => true,
  }
}
node server_with_no_db {
  class { 'databases': # this installs only the clients }
}

class databases (
  # By default, install no servers, just clients
  $pgsql_enabled => false,
  $mysql_enabled => false
)
{
  ...
}

class mydept::nextgeneration (
  # If not explicitly overridden, an undef value passed as a parameter to a class
  # assumes the default value in that class
  $mysql_enabled => undef,
  $pgsql_enabled => true
)
{
  class { 'databases':
    mysql_enabled => $mysql_enabled,
    pgsql_enabled => $pgsql_enabled,
  }
}

Как отметил комментатор, теперь есть отличная новая функция под названием Hiera, которая позволяет выгрузить значения по умолчанию в отдельную структуру данных, и вы должны изучить ее, если у вас есть Puppet 3.2. К сожалению, многие дистрибутивы Linux по-прежнему поставляются с версиями 2.6 или 2.7, так что это еще не вариант для вас.

Детали предыдущего ответа сохранены ниже

Обычно я обрабатываю что-то подобное: создаю файл default_parameters.pp, в котором нет ничего, кроме назначений по умолчанию для длинного списка переменных, поэтому в этом случае он будет содержать строку вроде $mysql_enabled = false. Затем этот файл включается в файл init.pp модуля. Тогда файл определений узлов будет выглядеть примерно так:

import "mymodule"

node myserver.local {   # NOTE: no inheritance!
  $mysql_enabled = true
  include mysql::server
}

node otherserver.local {
  include mysql::server
}

Затем в определении класса для mysql :: server вы проверяете, $mysql_enabled верно, и если да, используйте селектор на enable и ensure.

Это мгновенно прерывается, если node myserver.local наследует что-либо, потому что это заблокирует значение переменных во время наследования, и дальнейшие изменения внутри определения узла не будут иметь никакого эффекта, но в противном случае я использую этот метод повсюду, чтобы иметь отдельные компоненты вести себя по-разному, не создавая нескольких классов.

Если вам абсолютно необходимо иметь наследование, но список машин с включенным mysql невелик, вы можете выбрать альтернативный путь: вместо того, чтобы устанавливать переменную в определении узла, создайте свой селектор из $fqdn, по умолчанию отключено, а выбранные fqdns включены.

Попробуй это:

# In stripdown.pp : 
class stripdown {
    service { "mysql": 
         enable => "false", 
         ensure => "stopped" 
    }
}

# In mysql.pp : 
class mysql::server {  

    if defined(Service["mysql"]) {
        Service["mysql"] {  
            enable     => true,  
            ensure     => running,  
            hasrestart => true,  
            hasstatus  => true,  
            path       => "/etc/init.d/mysql",  
            require    => Package["mysql-server"],  
        }
    } else {
        service { "mysql":  
            enable     => true,  
            ensure     => running,  
            hasrestart => true,  
            hasstatus  => true,  
            path       => "/etc/init.d/mysql",  
            require    => Package["mysql-server"],  
        }
    }
}

# Then nodes in nodes.pp : 
node basenode {
    include stripdown 
}

node myserver.local inherits basenode {  
    include mysql::server
}

Это, конечно, связано с предупреждением о том, что у вас уже есть пакет ["mysql-server"], определенный в другом месте, и он не будет работать, как написано без него, из-за вашего require заявления.

Другая обнаруженная мной ошибка заключалась в том, что после параметров было слишком много пробелов. Параметры в строфе должны быть выровнены не более чем на 1 пробел больше, чем самое длинное имя параметра.

Дай этому уйти

# In stripdown.pp : 
class stripdown {
    service { "mysql": 
         enable => "false", 
         ensure => "stopped" 
    }
}

# In mysql.pp : 
class mysql::server inherits stripdown {  
    Service["mysqld"] {  
        enable      => true,  
        ensure      => running,  
        hasrestart  => true,  
        hasstatus   => true,  
        path        => "/etc/init.d/mysql",  
        require     => Package["mysql-server"],  
    } 
}

# Then nodes in nodes.pp : 
node basenode {
    include stripdown 
}

node myserver.local inherits basenode {  
    include mysql::server
}

Одна вещь, на которую вы можете захотеть взглянуть, - это виртуальные ресурсы, чтобы обойти множественное определение ресурсов. Документацию по этой теме можно найти: http://reductivelabs.com/trac/puppet/wiki/VirtualResources

Конечно, другим способом было бы просто создать объекты узла для каждого хоста, который не запускает mysql, а затем загрузить туда разделенный класс.