基于 Chef 版本的 Cookbook 依赖项
Cookbook dependencies based on chef version
我有一本使用其他食谱资源的包装食谱,但它们有不同的限制。我试着定义我的 metadata.rb 如下:
name 'yp_linko'
maintainer 'The Authors'
maintainer_email 'devops@yp.ca'
license 'all_rights'
description 'Installs/Configures yp_linko'
long_description 'Installs/Configures yp_linko'
version '1.3.4'
depends 'apt'
if chef_version '<= 12' then
depends 'ypg_tomcat'
else
depends 'yp_tomcat'
end
这没有用,因为厨师在收敛过程中抓住了两本食谱。我尝试了几种不同的语法(only_if、除非等...)并且 none 有效。有人有解决此问题的想法吗?
TL;DR
您正在以不应该使用的方式使用来自 Chef DSL 的约束。您需要根据布尔表达式而不是元数据约束进行分支。我提供了几种使用 String#to_f as examples (not recommended if you care about patch levels in semantic versioning), as well as the more accurate but often-overlooked Gem::Version.
的方法
不要使用分支约束
if chef_version '<= 12'
您正在尝试使用来自 DSL 的约束。此约束has a specific purpose:声明cookbook 支持的chef-client 版本,不提供逻辑分支。如果不查看 DSL 的底层 Chef 代码,我会说表达式不太可能按照您期望的方式提供您的 if-then 表达式。暂且不管这是否是正确的模式,您可以尝试通过几种不同的方式获取 Chef 工具的当前版本:
Chef-client 版本的分支,可能转换为 Float(通常是 String)。例如:
if Chef::VERSION.to_f <= 12
从 ohai 获取节点值,如:
if node['chef_packages']['chef']['version'].to_f <= 12
直接从客户端解析值,例如:
depends %x(chef-client --version).split[1].to_f <= 12 ? 'ypg_tomcat' : 'yp_tomcat'
但是,在所有情况下,您都必须处理这样一个事实,即传递给您的是包含语义版本控制的字符串,而不是浮点数或整数。因此,您必须弄清楚您真正想要如何解析信息,这可能容易出错(不过请参阅下面的使用 Gem::Version 的技巧)。在任何情况下,一旦你按照你想要的方式解析它,你就可以使用比较运算符匹配它以获得你想要的分支行为。
更好的选择
与其试图让元数据约束包含业务逻辑,不如将数据移出到属性中。考虑一个属性,例如 node['yp_linko']['tomcat_cookbook']
,您可以根据语义版本控制以外的其他一些可检测节点值来设置它。
另一种方法是将两本食谱声明为依赖项,然后 include 在 yp_linko 食谱的食谱中声明您想要的那个。例如,假设您没有在 Tomcat 食谱中声明不兼容的 chef-client 版本:
# metadata.rb
depends 'yp_tomcat'
depends 'ypg_tomcat'
# default.rb
if Chef::VERSION <= Gem::Version.new(12)
include ypg_tomcat::default
else
include yp_tomcat::default
end
最后,您首先应该考虑 运行 在基础架构中使用不同版本的 Chef 客户端是否真的有意义。可能有业务需要这样做,但这是您实际要解决的真正问题。在你的食谱中分支是基础设施问题的 X/Y 解决方案。您可能还有其他具有类似问题的食谱,因此至少值得考虑让您的所有客户都使用同一版本而不是在食谱级别解决问题是否更有意义。
我有一本使用其他食谱资源的包装食谱,但它们有不同的限制。我试着定义我的 metadata.rb 如下:
name 'yp_linko'
maintainer 'The Authors'
maintainer_email 'devops@yp.ca'
license 'all_rights'
description 'Installs/Configures yp_linko'
long_description 'Installs/Configures yp_linko'
version '1.3.4'
depends 'apt'
if chef_version '<= 12' then
depends 'ypg_tomcat'
else
depends 'yp_tomcat'
end
这没有用,因为厨师在收敛过程中抓住了两本食谱。我尝试了几种不同的语法(only_if、除非等...)并且 none 有效。有人有解决此问题的想法吗?
TL;DR
您正在以不应该使用的方式使用来自 Chef DSL 的约束。您需要根据布尔表达式而不是元数据约束进行分支。我提供了几种使用 String#to_f as examples (not recommended if you care about patch levels in semantic versioning), as well as the more accurate but often-overlooked Gem::Version.
的方法不要使用分支约束
if chef_version '<= 12'
您正在尝试使用来自 DSL 的约束。此约束has a specific purpose:声明cookbook 支持的chef-client 版本,不提供逻辑分支。如果不查看 DSL 的底层 Chef 代码,我会说表达式不太可能按照您期望的方式提供您的 if-then 表达式。暂且不管这是否是正确的模式,您可以尝试通过几种不同的方式获取 Chef 工具的当前版本:
Chef-client 版本的分支,可能转换为 Float(通常是 String)。例如:
if Chef::VERSION.to_f <= 12
从 ohai 获取节点值,如:
if node['chef_packages']['chef']['version'].to_f <= 12
直接从客户端解析值,例如:
depends %x(chef-client --version).split[1].to_f <= 12 ? 'ypg_tomcat' : 'yp_tomcat'
但是,在所有情况下,您都必须处理这样一个事实,即传递给您的是包含语义版本控制的字符串,而不是浮点数或整数。因此,您必须弄清楚您真正想要如何解析信息,这可能容易出错(不过请参阅下面的使用 Gem::Version 的技巧)。在任何情况下,一旦你按照你想要的方式解析它,你就可以使用比较运算符匹配它以获得你想要的分支行为。
更好的选择
与其试图让元数据约束包含业务逻辑,不如将数据移出到属性中。考虑一个属性,例如 node['yp_linko']['tomcat_cookbook']
,您可以根据语义版本控制以外的其他一些可检测节点值来设置它。
另一种方法是将两本食谱声明为依赖项,然后 include 在 yp_linko 食谱的食谱中声明您想要的那个。例如,假设您没有在 Tomcat 食谱中声明不兼容的 chef-client 版本:
# metadata.rb
depends 'yp_tomcat'
depends 'ypg_tomcat'
# default.rb
if Chef::VERSION <= Gem::Version.new(12)
include ypg_tomcat::default
else
include yp_tomcat::default
end
最后,您首先应该考虑 运行 在基础架构中使用不同版本的 Chef 客户端是否真的有意义。可能有业务需要这样做,但这是您实际要解决的真正问题。在你的食谱中分支是基础设施问题的 X/Y 解决方案。您可能还有其他具有类似问题的食谱,因此至少值得考虑让您的所有客户都使用同一版本而不是在食谱级别解决问题是否更有意义。