【问题标题】:are there iterators and loops in puppet?木偶中有迭代器和循环吗?
【发布时间】:2011-09-18 00:00:10
【问题描述】:

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

这样:

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

我有几十个目录,我真的厌倦了在 puppet 中声明它。这需要 15 LOC 的 bash。

有什么想法吗?

【问题讨论】:

    标签: deployment automation puppet


    【解决方案1】:

    旧版本的 puppet 语言不支持循环。

    但是您可以使用数组而不是简单的字符串作为标题,并使用相同的参数同时声明多个资源:

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

    您还可以通过以; 结束每个资源来声明许多具有不同参数的相同类型的资源,这比重复file{s 和}s 更紧凑:

    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;
    }
    

    (这将需要该目录结构的源以供 puppet 用作源)

    您可以define a new resource type 多次重复使用部分参数:

    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 中,他们引入了一些 experimental loops,但是这些功能可能会在以后的版本中更改或消失。

    【讨论】:

    • 谢谢!如何使它工作:文件{ [X,Y]:确保=链接,目标=> [X1+X,Y1+Y]}?
    • 您可以使用定义。在我的答案中添加了一个示例
    • 注意:最近(2013 年春夏),循环和迭代器已添加到语言中。
    【解决方案2】:

    从 3.2 版开始,有 lambdas

    您必须在 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',
        },  
    })
    

    【讨论】:

    • each() 解决方案是我迄今为止看到的唯一真正解决此问题的方法。
    • @markus,同意,但是,公平地说,当这个问题最初在 2011 年被问到时,我不确定它是否可用。希望这个问题可以浮现在这个问题的顶部,尽管如此人们不要浪费时间,现在 lambdas 可用了。
    • 如果您使用的是puppet apply,请确保启用未来的解析器puppet apply --parser=future
    【解决方案3】:

    从 Puppet 4(以及 Puppet 3 后期版本的“未来解析器”)开始,Puppet DSL 的迭代功能在形式和功能上与 Ruby 数组和哈希的某些方法相似:

    • each - 为数组或哈希的每个元素评估一个代码块(正式地,一个 lambda)
    • filter - 将 lambda 应用于数组或哈希的每个元素,并返回 lambda 评估为 true 的数组或哈希
    • map - 将 lambda 应用于数组或哈希的每个元素,并返回结果数组
    • reduce - 将 lambda 应用于数组或哈希的每个元素以构建单个结果,然后返回

    没有像 C 或 Java 那样的索引 for 循环,但您可以将 array sectioning 与上述任何函数结合起来,以实现对数据结构子集的迭代。沿着 C 或 Java while 循环的行没有无限迭代。

    当然,您仍然可以使用其他答案中描述的以资源为中心的方法,有时其中一种确实是最好的可用方法。但是,您不能再使用 Ruby DSL。它已从 Puppet 4 中完全删除。在迭代函数、定义自定义函数的能力、以数据为中心的方法受到青睐以及所有 Puppet 的历史标准特性中,Ruby DSL 似乎并没有被错过。

    【讨论】:

      【解决方案4】:

      是的。 “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 版起,此功能为 deprecated

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-29
        • 1970-01-01
        • 1970-01-01
        • 2015-02-08
        • 1970-01-01
        相关资源
        最近更新 更多