Puppet 2.7.x – 全局variables – 追加

没有深入到杂草,Nginx迫使我的手,以通过虚幻和map指令完成一些魔术。

是否有一个优雅的(相对)解决scheme来跨多个定义调用共享一个variables,它允许每个定义调用将其数据附加到全局variables? 在软件中,这将被称为单身。

– 杂草 –

Nginx有一个map指令,它决定了哪个上游服务器池应该被传递,如下所示:

 map $http_host $upstream_pool { hostnames; blog.example.com blog_example_com; repo.example.com repo_example_com; default example_com; } 

如您所见,对blog.example.com的任何请求都将传递到blog_example_com上游服务器池(通过proxy_pass )。

问题是map指令的语法是它只能包含在主要的http块(nginx.conf)中,而vhost特定的指令(如upstreamlocation可以包含在vhostconfiguration的server块中。

我的nodes.pp清单看起来像这样:

  service-a-1.example.com inherits project_dev { nginx::vhost { 'mothership': } nginx::vhost { 'mothership_blog': } nginx::vhost { 'repo': } } 

正如你所看到的,在一个成功的木偶运行之后,我应该在/etc/nginx/vhost.d/目录中得到3个不同的vhostconfiguration文件。

我遇到的问题是,为了使map指令工作,我需要知道哪些虚拟主机已经加载,所以我可以将他们各自的上游id添加到我在主configuration中定义的map指令中: /etc/nginx/nginx.conf http块中的/etc/nginx/nginx.conf (其中只能有一个)。

– 我曾尝试过 –

我有一个global.pp文件,它做了一些“引导”,并在这个文件中添加了一个$singleton = ''语法,然后在nginx :: vhost定义中,我添加了这个语法:

 $tpl_upstream_pool_labels = inline_template("<% tpl_upstream_pools.keys.sort.each do |role| %><%= role %>_<%= tpl_domain_primary %>_<%= tpl_domain_top_level %>|<% end %>") $singleton = "${singleton}${tpl_upstream_pool_labels}" notify { "\n--------------------- Nginx::Conf::Vhost::Touch | Timestamp: ${timestamp} | Pool labels: ${singleton} -------------------------\n": } 

哪个应该导致pipe道分隔的上游id列表。 如前所述,在nodes.pp清单中,我对nginx :: vhost进行了三次调用,并希望每个调用都附加$singleton全局variables,但不是,它只包含最后一次调用的数据。

我也试图通过写一个临时文件来解决这个问题:

 $temp_file_upstream_pool_labels_uri = "/tmp/puppet_known_upstreams_${timestamp}.txt" exec { "event_record_known_upstream_${name}" : command => "touch ${temp_file_upstream_pool_labels_uri} && echo ${tpl_upstream_pool_labels} >> ${temp_file_upstream_pool_labels_uri}", provider => 'shell' } 

然后在nginx :: conf :: touch的定义中,主要的configurationnginx.conf是由puppet写的,我试过这个:

 $temp_file_upstream_pool_labels_uri = "/tmp/puppet_known_upstreams_${timestamp}.txt" $contents = file($temp_file_upstream_pool_labels_uri) 

理论上应该把文件的内容加载到$ contentsvariables中。 但是当我使用这种方法运行puppet时,我得到一个文件不存在的错误。 我确保nginx :: conf :: touch调用不会在所有虚拟主机被考虑之前发出,但仍然无济于事。

Puppet中的全局variables的问题是你不能实际追加到它们。 允许使用+=语法,但它会创build全局的本地副本 ,并附加右侧的值。

我已经实现了一个你想要的模式,但我并不自豪,不能推荐使用它。 不过,既然你问,这里是:

 class nginx::conf { $global = '' file { '/etc/nginx/nginx.conf': content => template(...) } } 

至less在2.7.x可以附加类的variables。

 define nginx::vhost(...) { include nginx::conf $nginx::conf::global += "new content here" nginx::override_conf_content { "for-vhost-$name": } } 

神秘的事情发生在神秘的最后一行中,它实例化了另一个define

 define nginx::override_conf_content() { include nginx::conf $global = $nginx::conf::global File<| title == '/etc/nginx/nginx.conf' |> { content => template(...) } } 

nginx.confcontent属性被模板的另一个评估结果覆盖,并带有新的variables值。

充分披露,我不知道为什么这个工程。 它可能不应该,并可能依靠一个晦涩的错误。 它可能会停止在未来的版本工作。

请注意,我把它叫做$global而不是$singleton ,因为就是这样。 单身人士可以用来实现全局的语义,但他们不是一回事。

最后,尽pipe我可以感受到Puppet 3更新所面临的痛苦,但是您应该花点时间并开始实施。 我们都可能无法承受运行2.x更长的时间。

添加另一个答案,以保持问题分开。

结合execfile()是有缺陷的,因为它们在不同的层面上工作。

exec资源被添加到目录并发送到代理,在编译完成后评估它。 由于您正在尝试编译时收集信息(在使用file()函数收集信息之前),因此不能依赖任何资源。

应该可以通过依赖生成函数而不是exec资源来构build您的想法。