Puppet 2.7.x - 全局变量 - 附加

Puppet 2.7.x - 全局变量 - 附加

无需深入探究,Nginx 迫使我使用 vhosts 和map指令来实现一些神奇的效果。

是否有一个优雅的(相对)解决方案可以在多个定义调用之间共享一个变量,从而允许每个定义调用将其数据附加到全局变量?在软件中,这称为单例。

杂草

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 特定的指令(例如upstream和)location可以包含在servervhost 配置的块中。

我的 nodes.pp 清单如下所示:

 service-a-1.example.com inherits project_dev {

     nginx::vhost { 'mothership': }
     nginx::vhost { 'mothership_blog': }
     nginx::vhost { 'repo': }
}

/etc/nginx/vhost.d/如你所见,在成功运行 puppet 之后,我应该在目录中得到 3 个不同的 vhost 配置文件。

我遇到的问题是,为了使map指令起作用,我需要知道哪些虚拟主机已加载,这样我就可以将它们各自的上游 ID 添加到指令中map,该指令我在主配置中已定义:/etc/nginx/nginx.confhttp块内(其中只能有一个)。

— 我尝试过的 —-

我有一个 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": }

这应该会生成一个以竖线分隔的上游 ID 列表。如前所述,在 nodes.pp 清单中,我对 nginx::vhost 进行了三次调用,并希望$singleton每次调用后都会附加全局变量,但事实并非如此,它仅包含最后一次调用的数据。

我还尝试通过编写临时文件来解决这个问题,如下所示:

$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 定义中,主要配置 nginx.conf 由 puppet 写入,我尝试了这个:

$temp_file_upstream_pool_labels_uri = "/tmp/puppet_known_upstreams_${timestamp}.txt"

$contents = file($temp_file_upstream_pool_labels_uri)

理论上,它应该将文件的内容加载到 $contents 变量中。但是当我使用这种方法运行 puppet 时,我收到文件不存在的错误。我确保在考虑完所有 vhost 之后才进行 nginx::conf::touch 调用,但仍然无济于事。

答案1

Puppet 中的全局变量的问题在于你无法实际附加到它们。+=语法是允许的,但它会创建一个本地副本全局的,并附加右侧的值。

我已经实现了一个可以满足你要求的模式,但我并不为此感到自豪,也不建议使用它。不过,既然你问了,那就这样吧:

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

来自类的变量至少在 中附加2.7.x

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(...)
    }
}

使用对模板的另一次评估的结果和新的变量值来覆盖该content属性。nginx.conf

坦白说,我不确定为什么这样做有效。它可能不应该,并且可能依赖于一个不为人知的错误。它可能在未来的版本中停止工作。

请注意,我称其$global为 而不是$singleton,因为它就是 。单例可用于实现全局变量的语义,但它们不是一回事。

最后,尽管我能体会到您在面对 Puppet 3 更新时的痛苦,但您确实应该花点时间开始更新。我们可能都承受不起2.x太长时间的等待了。

答案2

添加另一个答案以区分问题。

这种方法存在缺陷execfile()因为它们的作用层面非常不同。

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

你应该能够通过依赖产生功能而不是exec资源。

相关内容