Chef Policyfile.rb 'include_policy' 不保证策略依赖项的不可变性



假设我在一本名为motd:的食谱中有一个Polcyfile.rb

name 'motd'
default_source :chef_repo, "../"
include_policy "Policyfile", path: "../environment"
run_list 'motd'

recipes/default.rb:

file '/etc/motd' do
content node['message']
end

我有另一本名为environment的食谱,里面有一个Policyfile.rb:

name 'environment'
default_source :chef_repo, "../"
run_list 'environment'

它有一个空的recipes/default.rbattributes/default.rb,带有:

default['message'] = 'i am a message'

我在environment目录中运行chef install Policyfile.rb来生成锁文件。当我从motd目录运行kitchen converge,然后从kitchen login运行时,我将获得控制台的预期输出:

This system is built by the Bento project by Chef Software
More information can be found at https://github.com/chef/bento
i am a message

现在我去更新environment/attributes/default.rb

default['message'] = 'i am updated'

不要environment运行chef update Policyfile.rb,并从motd再次运行kitchen converge。我的期望是kitchen login不会反映我的更新,因为motd中的Policyfile.lock.json尚未针对所包含的environment策略更新其revision_id。但令我惊讶的是,我确实在控制台中看到了更新后的消息。我确实看到Policyfile.lock.json有一个新的根revision_id,而cookbook_locks->environment->identifier已经改变了。但是,我仍然认为,在这种情况下,如果我的依赖项Policyfile.rb中的食谱发生了变化,并且计算不匹配其Policyfile.lock.jsonrevision_id的哈希,那么我仍然应该看到旧的输出,或者这里应该有其他警告。

我想我只是想更全面地理解这里的概念。一方面,motd的根revision_id发生了变化,因此我在某种意义上实现了幂等性。但另一方面,environment依赖关系的revision_id与其组件食谱不匹配。有人能解释一下为什么这有意义吗?

chef installtest-kitchen的交互方式似乎存在漏洞或可能存在功能。chef install所做的只是根据版本号进行验证,如果你更新食谱的版本而不使用chef update重新生成,那么你会得到一个异常:

Error: Failed to install cookbooks from lockfile
Reason: (CookbookOmnifetch::CookbookValidationFailure) The cookbook downloaded for Cookbook 'xxxxxxx' = 1.2.3 {:path=>"."} did not satisfy the constraint.

如果您修改了烹饪书,测试厨房将运行chef install,并将烹饪书文件同步到您正在构建的虚拟实例,并对其运行chef客户端,这意味着任何本地修改都将自动进行,而无需应用chef update

这不是生产设置中的情况,因为您需要使用chef push将烹饪书上传到由烹饪书的sha版本控制的cookbook_artifacts存储库。由于客户端根据锁定文件中的sha提取cookbook_artifact,因此这将在部署过程中失败。由于test-kichen不使用chef push,因此它没有您在部署中看到的不变性特性。

可以说,这是一个测试厨房功能,否则测试厨房将需要切换到每次默认运行chef update,或者强制用户在两次运行之间手动运行chef update。但是,保持反映生产的锁定文件,以便工作流程在食谱上迭代,并仅在推送时重新生成锁定文件,这可能是工作流程的一项功能。如果有人觉得这实际上是一个有害的bug,你可以针对测试厨房或厨师cli打开一个问题来修复它(但你需要争论引人注目的工作流功能,而不是哲学(。尽管测试厨房的方式并非一成不变,但这与生产环境中策略文件的不变性没有任何关系,我认为这就是这个问题的意义所在。

revision_id不是冻结依赖关系的东西。不管它是运行列表中的食谱还是依赖项。只有烹饪书版本用于锁定。

假设您已经有了一个锁定文件,例如您的environment食谱版本和食谱集的路径。

[...]
"cookbook_locks": {
"environment": {
[...]
"source": "../environment"
}
}
[...]
"solution_dependencies": {
"Policyfile': [
["motd", "= 1.2.3"],
["environment", "= 2.7.8"]
]
}
[...]

然后,如果并且只有当您在../environment/metadata.rb中更改食谱的版本时,您才会收到错误,说明找不到特定版本的食谱。在这种情况下,您必须重新生成锁定文件。

对食谱的任何其他更改都不会引发任何错误。这是意料之中的行为。想象一下,如果你必须为你所做的每一次更改重新生成锁文件,那将是一大笔开销。

将policyfile中的revision_id视为policyfile的一个版本。由于没有策略文件的向后兼容性这样的概念,因此不需要使用语义版本控制,并且在这种情况下,一个长的唯一字符串(而不是像版本那样随机生成(就足够了。这就是为什么chef show-policy将向您显示在特定策略组中应用的策略文件的修订,以显示此版本已部署到此组。

最新更新