基于厨师版本的Cookbook依赖项

问题描述 投票:0回答:1

我有一个使用其他烹饪书中的资源的包装食谱,但它们有不同的约束。我尝试定义我的metadata.rb如下:

name 'yp_linko'
maintainer 'The Authors'
maintainer_email '[email protected]'
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,除非,等等......)但没有一种方法。有人有想法解决这个问题吗?

ruby chef metadata chef-recipe
1个回答
1
投票

TL; DR

您正在使用Chef DSL中的约束,其方式是不打算使用它。您需要基于布尔表达式而不是元数据约束进行分支。我提供了几种使用String#to_f作为示例的方法(如果您关心语义版本中的补丁级别,则不推荐),以及更准确但经常被忽略的Gem::Version

不要使用约束进行分支

if chef_version '<= 12'

您正在尝试使用DSL中的约束。这个约束has a specific purpose:声明cookbook支持的chef-client版本,而不是提供逻辑分支。如果没有查看DSL的底层Chef代码,我会说这个表达式不太可能像你期望的那样为你的if-then表达式提供信息。暂时搁置这是否是正确的模式,您可以尝试以几种不同的方式获取当前版本的Chef工具:

  1. 在chef-client版本上分支,可能被转换为Float(通常是String)。例如: if Chef::VERSION.to_f <= 12
  2. 从ohai获取节点值,例如: if node['chef_packages']['chef']['version'].to_f <= 12
  3. 直接从客户端解析值,例如: depends %x(chef-client --version).split[1].to_f <= 12 ? 'ypg_tomcat' : 'yp_tomcat'

但是,在所有情况下,您将不得不处理这样一个事实:您正在传递包含语义版本控制的String,而不是Float或Integer。因此,您必须弄清楚您真正想要解析的信息,这可能容易出错(尽管如此,请参阅下面的使用Gem :: Version的技巧)。无论如何,一旦你按照你想要的方式解析它,你可以使用比较运算符来匹配它,以获得你想要的分支行为。

更好的选择

您可能应该将数据移出到属性,而不是尝试使元数据约束保持业务逻辑。考虑一个属性,例如node['yp_linko']['tomcat_cookbook'],您可以根据除语义版本控制之外的其他一些可检测节点值来设置该属性。

另一种方法是将两个烹饪书声明为依赖,然后在你的yp_linko食谱中的食谱中include你想要的那个。例如,假设您尚未在Tomcat cookbook中声明不兼容的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解决方案。您可能还有其他类似问题的烹饪书,因此至少值得考虑让所有客户使用相同版本而不是在菜谱级解决问题更有意义。

© www.soinside.com 2019 - 2024. All rights reserved.