I'm just learning about Chef, and I'm confused about the best way to handle a situation where there's a single config file that may need to be modified by multiple recipes. The specific case I have is with AWS Cloudwatch Logs. It has a single configuration file (no way that I see to include other files), which needs to list out all of the logfiles it collects. I have different recipes (e.g. a web server, a mail server, etc.) that will cause different logfiles to be created. When those recipes run, I want their logfiles to be added to the AWS Logs config file. But it doesn't seem safe to just append that to the file, because if the recipe is re-run, it will be added again. And I want to keep the logic about which logfiles exist within the recipe where the software that creates them is installed. I'd like to be able to just add a recipe to the runlist and have its logs get added to the config file (and vice versa), without the mail server recipe having to know anything about the files the web server creates and so on.
What is the right way to do this?
You need to have a CloudWatch recipe that actually creates the config file. Each of your other recipes can add some node attributes to indicate what log files they need added, and then the CloudWatch cookbook could grab those attributes and use them to build the config file.
For example:
node['logs']['nginx']['somevhost'] = %w(/path/to/log /path/to/other/log)
node['logs'].each do |app|
app.each do |component|
<add to some collection structured for CloudWatch's config file>
end
end
I would suggest you take a look at the infochips's silverware cookbook. It has a nice library you can use to advertise your log files in the webserver and mailserver cookbooks, and then discover them in the CloudWatch cookbook.