假设我在一本名为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.rb
和attributes/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 install
与test-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
将向您显示在特定策略组中应用的策略文件的修订,以显示此版本已部署到此组。