Chef gets a bad rap for being “hard” — especially when compared to Ansible .. This is especially true when developers of Chef cookbooks don’t understand the two-pass model .. A common question amongst new Chef cookbook developers goes something like this: “I want to run a shell command and capture its output (i.e. STDOUT) .. I then want to loop through that shell command’s output to run other Chef resources, and I want those other Chef resources to be aware of the shell command’s output .. How can I do that ??” .. Sometimes it’s easier to use bullets:
- run a shell command
- the output of the shell command == A, B, C
- loop through the shell command’s output one at a time
- run other Chef resources per loop item
- other Chef resources are aware of the loop item value
Often, the new Chef cookbook developer will try and run a Ruby loop in the raw, which will execute during the compile phase — this is a big no-no .. Instead, you should run the shell command, using
shell_out, in a Chef
ruby_block resource .. This will give you access to the shell command’s output where you can manipulate the output using good ol’ fashioned Ruby, and then “notify” other Chef resources as desired ..
One thing to be aware of is to make sure you are lazily evaluating properties in a resource that can’t be known until the execution phase of the chef-client run. Alan Thatcher has a nice writeup here about the hows and the whys ..
Enough talk — show me the code !!
So, is Chef “hard” ?? I would argue no — but it sure is nuanced, and for good reason ..