Puppet中是否有迭代器和循环?

37

当我定义资源时,例如为了确保目录结构,是否有可用的循环?

就像这样:

  for X in [app1,app2] do:
    file { '/opt/app/' + X:
      ensure => directory,
      owner  => 'root',
      group  => 'root',
      mode   => '0644',
    }

我有数十个目录,已经厌倦了在puppet中声明它们... 这需要15行bash代码。

有什么建议吗?

4个回答

41

旧版的Puppet语言不支持循环。

但你可以使用数组代替简单字符串作为标题,并同时声明具有相同参数的多个资源:

$b = '/opt/app'
file { [ "$b/app1", "$b/app2" ]:
  ensure => directory,
  owner  => 'root',
  group  => 'root',
  mode   => 0644,
}

如果您在每个资源后使用分号;来结束它,那么可以声明许多具有不同参数的相同类型的资源,这比重复文件{以及}更加紧凑:

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;
}
需要翻译的内容:(that would require having a source of that directory structure for puppet to use as the source)
你可以定义一个新的资源类型,以便在多个参数中重复使用其中一部分。
需要翻译的内容:You can define a new resource type to reuse a portion of the param multiple times:
你可以定义一个新的资源类型,以便多次重复使用参数的一部分。
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中,他们引入了一些实验性循环,但这些功能可能会在以后的版本中更改或消失。


1
谢谢!如何让这个工作起来:文件 {[X,Y]:ensure = link,target => [X1 + X,Y1 + Y]}? - user425720
1
你可以使用宏定义。我在我的回答中添加了一个例子。 - freiheit
2
注意:最近(2013年春/夏季),循环和迭代器已被添加到该语言中。 - freiheit

27

从版本3.2开始,有lambda函数

您必须在puppet.conf中设置parser = future

$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',
    },  
})

5
到目前为止,我看到的唯一真正解决这个问题的方法是使用 each() 函数。 - markus
@markus,同意,但公平起见,我不确定在2011年提出这个问题时是否可用。希望这个问题能够浮现到最上面,这样人们就不会浪费时间了,现在_lambdas_是可用的。 - quickshiftin
4
如果您正在使用 puppet apply 命令,请确保启用未来解析器,命令为 puppet apply --parser=future。注意不要改变原文意思,并尽可能使翻译通俗易懂。 - quickshiftin

4
自 Puppet 4 版本(以及 Puppet 3 的后期版本中的“未来解析器”)起,Puppet DSL 具有类似于 Ruby 数组和哈希表方法的迭代函数:
  • each - 为数组或哈希表的每个元素评估一段代码块(形式上为 lambda)
  • filter - 将 lambda 应用于数组或哈希表的每个元素,并返回 lambda 评估为 true 的元素的数组或哈希表
  • map - 将 lambda 应用于数组或哈希表的每个元素,并返回结果的数组
  • reduce - 将 lambda 应用于数组或哈希表的每个元素以构建单个结果,并返回该结果

没有类似于C或Java的索引for循环,但是您可以结合数组分区和上述任何函数之一,以对数据结构的子集进行迭代。没有类似于C或Java while循环的无限迭代。

当然,您仍然可以使用其他答案中描述的面向资源的方法,有时其中一个确实是最佳可用方法。然而,您不能再使用Ruby DSL;它完全从Puppet 4中删除。在迭代函数中,定义自定义函数的能力,数据中心方法的崛起,以及所有Puppet历史标准功能,似乎并不太需要Ruby DSL。


2
是的。"Ruby DSL"可以帮助,只需要在清单文件中使用扩展名".rb"而不是".pp",您就可以像这样定义puppet "type":
define 'myapps::structure', :applist do
   @applist.each do |app|
       file( @name+'/'+app, 
             :ensure => directory,
             :owner  => 'root',
             :group  => 'root',
             :mode   => '0644')
   end
end

类和节点也可以以类似的方式定义。然而请注意,自版本3发布以来,此功能被弃用


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接