Let's say I have a Polcyfile.rb in a cookbook called motd:
name 'motd'
default_source :chef_repo, "../"
include_policy "Policyfile", path: "../environment"
run_list 'motd'
and a recipes/default.rb:
file '/etc/motd' do
content node['message']
end
I have another cookbook called environment which has a Policyfile.rb:
name 'environment'
default_source :chef_repo, "../"
run_list 'environment'
It has an empty recipes/default.rb and attributes/default.rb with:
default['message'] = 'i am a message'
I run chef install Policyfile.rb in environment dir to generate the lock file. When I run kitchen converge from motd dir and then kitchen login, I get my expected output to console:
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
Now I go and update environment/attributes/default.rb to be
default['message'] = 'i am updated'
I DO NOT run chef update Policyfile.rb for environment and run kitchen converge again from motd. My expectation is that kitchen login will not reflect my update because Policyfile.lock.json in motd has not updated its revision_id for the included environment policy. But much to my surprise I indeed see the updated message in the console. I do see that Policyfile.lock.json has a new root revision_id and that cookbook_locks->environment->identifier has changed. But still, I would think that in this case, if the cookbooks in my dependency Policyfile.rb have changed and don't compute to match the hash of its Policyfile.lock.json revision_id then I should still see the old output or there should be some kind of other warning here.
I guess I'm just trying to understand the concept here more fully. On the one hand, the root revision_id for motd changed so I have achieved idempotency in one sense. But on the other hand the revision_id for environment dependency and its component cookbook don't match. Can someone explain why this makes sense?
It seems like there is a bug or possibly a feature in the way that
chef installinteracts withtest-kitchen. All thatchef installdoes is validate against version numbers, and if you update the version of the cookbook without regenerating with achef updatethen you'll get an exception:If you modify the cookbook, test-kitchen will run
chef installand will the synchronize the cookbook files to the virtual instance you are building and will run chef-client against them, which means any local modifications are picked up automatically without achef updateneeding to be applied.This isn't how it happens in production settings, since you need to use
chef pushto upload the cookbooks to the cookbook_artifacts repository, which is versioned by the sha of the cookbook. Since the client pulls down the cookbook_artifact based on the sha in the lockfile this will fail during deployment. Sincetest-kichendoesn't usechef pushit doesn't have the immutability features you'd see in deployments.It could be argued this is a test-kitchen feature, otherwise test-kitchen would need to switch to always running
chef updateevery single time by default, or forcing users to manually runchef updatebetween runs. But keeping the lockfile reflecting production so that the workflow is to iterate on the cookbook and only regenerate the lockfile when it is time to push may be a workflow feature. If anyone feels that this is an actually harmful bug, you can open an issue against test-kitchen or chef-cli in order to get it fixed (but you'll need to argue compelling workflow features, not philosophy). The way that test-kitchen isn't immutable though doesn't have any bearing on the immutability of policfiles in production settings, though, which I think is what this question is about.