如何在puppet清单中惰性地定义类

如何在puppet清单中惰性地定义类,puppet,Puppet,我有一个具有不同角色的系统,a B C。有一个类daemon::conf,它定义了conf,并连接了所有类参数的配置,例如 class daemon::conf ( global_config = {} a_config = {} b_config = {} c_config = {} ) { concat::fragment {...} } 所以当我这样做的时候: class hg_mysystem::mycluster::hybrid {

我有一个具有不同角色的系统,a B C。有一个类
daemon::conf
,它定义了conf,并连接了所有类参数的配置,例如

class daemon::conf (
  global_config = {}
  a_config      = {}
  b_config      = {}
  c_config      = {}
) {
concat::fragment {...}
}
所以当我这样做的时候:

class hg_mysystem::mycluster::hybrid {
  include daemon::A
  include daemon::B
}
我想要:

$ cat /etc/mysystem/config
[Global]
...
[A]
...
[B]
...
每个守护进程都被定义为
守护进程::A、守护进程::B、守护进程::C
,但它们使用自己的参数调用
守护进程::conf
,这些参数在
.pp
清单文件中的hiera中定义。现在我需要创建一个具有2或3个角色的节点(编写
include daemon::a;include daemon::B
等),但是我在重新定义类时遇到了一个问题,因为daemon::conf是在所有的a、B和C中定义的

我的第一个想法是在一个节点上定义类,并添加
if defined(class['daemon::conf']){add argument to the defined class}或者{class{'daemon::conf'…}}
,但我不知道如何从清单创建动态hiera变量,或者如何从清单执行hiera样式的赋值。 我还搜索了如何使用这些虚拟资源执行类的惰性初始化,但我不明白这有什么帮助,因为realize没有覆盖参数,而使用realize只执行
realize class['daemon::conf']
而不是
realize class['daemon::conf']{b_config={…}
。 是否有任何方法可以使用通知另一个基于类的数据构建conf的类的子类来重构
daemon::conf

编辑:

我遵循第二种方法,将
daemon::conf
拆分为
daemon::conf
daemon::conf::A
daemon::conf::B

class daemon::conf (...) {
  concat { '/etc/daemon/conf':
    owner   => 'root',
    group   => 'root',
    mode    => '0664',
    require => Package['daemon'],
  }

  Concat::Fragment <<| target == '/etc/daemon/config' |>>

  concat::fragment { 'daemon.conf':
    tag     => "daemon.conf",
    target  => '/etc/daemon/config',
    order   => '01',
    content => template('daemon/daemon.conf.erb'),
  }
}

define daemon::conf::A (...) {
  include ::daemon::conf

  @@concat::fragment { "${::hostname}.daemon.conf":
    tag     => "daemon.conf",
    target  => '/etc/daemon/config',
    order   => '20',
    content => template('daemon/daemon.conf-A.erb'),
  }

}

class daemon::conf::B (...) {
  include ::daemon::conf

  concat::fragment { $::hostname:
    tag     => "daemon.conf",
    target  => '/etc/daemon/config',
    order   => '10',
    content => template('daemon/daemon.conf-B.erb'),
  }

}

class daemon::A (
  $A_addr,
  $port,
) {
  include ::daemon::conf

  daemon::conf::A { $::hostname:
    addr => $A_addr,
    port => $port,
  }
}

class daemon::B (
  $B_rack_loc,
) {
  include ::daemon::conf

  class {'::daemon::conf::B':
    B_config => {
      B_rack_location => $B_rack_loc,
    }
  }
}

但是,我得到了角色B的多个配置以及所有3台主机的多个配置。我会犯什么错误?如何纠正?谢谢是否应该更改“”语句?

任何解决方案都需要适应这样一个事实:给定类的所有参数的值都是在第一次计算该类的声明时确定的,无论该声明是类似资源的声明还是类似包含的声明。只有在所有在第一次使用include-like表单之后进行求值的声明都使用其中一个时,才允许使用多个声明,这也是在大多数情况下应该避免使用资源类声明的原因之一

有多种方法可以考虑这些因素。一种是颠倒逻辑:不是让所有的
守护进程::X
类都声明
守护进程::conf
,而是集中声明一次,并向其传递要配置的角色列表。然后让它根据角色列表声明适当的
daemon::conf::X
类:

class daemon::conf (
  $global_config = {}
  $roles =         []
) {
  concat { ... }
  concat::fragment {...}
  $roles.each { |$role|
    contain "daemon::conf::${role}"
  }
}

另一种方法是免除中央
守护程序::conf
类声明每个角色配置的责任。这是可能的,因为您正在使用Concat从片段构建配置。puppetlabs::concat的一个关键特性是
concat::fragment
s可以相互独立地声明,也可以声明它们所贡献的文件的
concat

class daemon::conf (
  $global_config = {}
) {
  concat { ... }
  concat::fragment {...}  # general configuration only
}

class daemon::a::conf (...) {
  concat::fragment {...}  # daemon A configs
}

class daemon::b::conf (...) {
  concat::fragment {...}  # daemon B configs
}

class daemon::a (...) {
  include daemon::conf     # (maybe)
  contain daemon::a::conf
  # ...
}

class daemon::b (...) {
  include daemon::conf     # (maybe)
  contain daemon::b::conf
  # ...
}

...

任何解决方案都需要考虑这样一个事实:给定类的所有参数的值都是在第一次计算该类的声明时确定的,无论该声明是类似资源的声明还是类似包含的声明。只有在所有在第一次使用include-like表单之后进行求值的声明都使用其中一个时,才允许使用多个声明,这也是在大多数情况下应该避免使用资源类声明的原因之一

有多种方法可以考虑这些因素。一种是颠倒逻辑:不是让所有的
守护进程::X
类都声明
守护进程::conf
,而是集中声明一次,并向其传递要配置的角色列表。然后让它根据角色列表声明适当的
daemon::conf::X
类:

class daemon::conf (
  $global_config = {}
  $roles =         []
) {
  concat { ... }
  concat::fragment {...}
  $roles.each { |$role|
    contain "daemon::conf::${role}"
  }
}

另一种方法是免除中央
守护程序::conf
类声明每个角色配置的责任。这是可能的,因为您正在使用Concat从片段构建配置。puppetlabs::concat的一个关键特性是
concat::fragment
s可以相互独立地声明,也可以声明它们所贡献的文件的
concat

class daemon::conf (
  $global_config = {}
) {
  concat { ... }
  concat::fragment {...}  # general configuration only
}

class daemon::a::conf (...) {
  concat::fragment {...}  # daemon A configs
}

class daemon::b::conf (...) {
  concat::fragment {...}  # daemon B configs
}

class daemon::a (...) {
  include daemon::conf     # (maybe)
  contain daemon::a::conf
  # ...
}

class daemon::b (...) {
  include daemon::conf     # (maybe)
  contain daemon::b::conf
  # ...
}

...

如果我能用hiera编写每个参数,我当前的实现就不会有问题。现在来看第一个示例,daemon::B如何从其清单中添加参数,以便
包含“daemon::conf::${role}”
将包含参数化的类。我是否应该将每个角色的所有配置逻辑都移动到中央配置类中?@εεόφιλοοορατίΔης,要使当前实现这样的功能正常工作,您至少需要将class
daemon::conf
的类似于资源的类声明更改为包含类似的类声明。在Hiera中拥有所有参数数据将有助于实现这一点,但这本身还不够。特别是,即使没有指定任何参数,也不允许同一类的多个类似资源的声明。对于这个问题,第一种选择取决于
daemon::conf
以某种方式拥有为每个角色发出正确配置所需的所有信息。如果您需要
守护进程::a
等类来动态确定配置属性,那么第二种方法更可行。非常感谢您的帮助,我现在有了我在编辑的问题中写的这个小问题,我已经完成了@,我认为没有必要为您的特定目的导出或收集
concat::fragment
资源。只需将它们声明为普通资源,如本答案中所示。(那么,没有必要收集它们,因为它们已经在目录中了。)如果我