{"id":6540,"date":"2017-03-10T11:49:17","date_gmt":"2017-03-10T03:49:17","guid":{"rendered":"http:\/\/rmohan.com\/?p=6540"},"modified":"2017-03-10T11:49:17","modified_gmt":"2017-03-10T03:49:17","slug":"for-loops-in-chef","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=6540","title":{"rendered":"for loops in Chef"},"content":{"rendered":"<div class=\"line number1 index0 alt2\"><code class=\"ruby keyword\">for<\/code> <code class=\"ruby plain\">config <\/code><code class=\"ruby keyword\">in<\/code> <code class=\"ruby plain\">[ <\/code><code class=\"ruby string\">\"contacts.cfg\"<\/code><code class=\"ruby plain\">, <\/code><code class=\"ruby string\">\"contactgroups.cfg\"<\/code> <code class=\"ruby plain\">] <\/code><code class=\"ruby keyword\">do<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"ruby spaces\">\u00a0\u00a0<\/code><code class=\"ruby plain\">remote_file <\/code><code class=\"ruby string\">\"\/etc\/nagios3\/#{config}\"<\/code> <code class=\"ruby keyword\">do<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"ruby spaces\">\u00a0\u00a0\u00a0\u00a0<\/code><code class=\"ruby plain\">source <\/code><code class=\"ruby string\">\"#{config}\"<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"ruby spaces\">\u00a0\u00a0\u00a0\u00a0<\/code><code class=\"ruby plain\">owner <\/code><code class=\"ruby string\">\"root\"<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"ruby spaces\">\u00a0\u00a0\u00a0\u00a0<\/code><code class=\"ruby plain\">group <\/code><code class=\"ruby string\">\"root\"<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"ruby spaces\">\u00a0\u00a0\u00a0\u00a0<\/code><code class=\"ruby plain\">mode <\/code><code class=\"ruby constants\">0644<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"ruby spaces\">\u00a0\u00a0\u00a0\u00a0<\/code><code class=\"ruby plain\">notifies <\/code><code class=\"ruby color2\">:restart<\/code><code class=\"ruby plain\">, resources(<\/code><code class=\"ruby color2\">:service<\/code> <code class=\"ruby plain\">=&gt; <\/code><code class=\"ruby string\">\"nagios\"<\/code><code class=\"ruby plain\">), <\/code><code class=\"ruby color2\">:delayed<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"ruby spaces\">\u00a0\u00a0<\/code><code class=\"ruby keyword\">end<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"ruby keyword\">end<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><\/div>\n<div class=\"line number9 index8 alt2\">\n<h2>Write it in the order you want it to run<\/h2>\n<p>Chef executes resources in the order they appear in a recipe. Coming to Chef from <a title=\"Various (Puppet Labs): Puppet is IT automation software that helps system administrators manage infrastructure throughout its lifecycle.\" href=\"https:\/\/puppetlabs.com\/puppet\/what-is-puppet\/\">Puppet<\/a>, I found this to be a welcome surprise. Need to install the NTP daemon and then make sure the service is started? No problem. Just put your <a title=\"Various (Opscode): The service resource is used to manage a service.\" href=\"http:\/\/docs.opscode.com\/chef\/resources.html#service\">service resource<\/a> after your <a title=\"Various (Opscode): The package resource is used to manage packages.\" href=\"http:\/\/docs.opscode.com\/chef\/resources.html#package\">package resource<\/a>.<\/p>\n<pre><code>package 'ntp' do\r\n  action :install\r\nend\r\n\r\nservice 'ntp' do\r\n  action :start\r\nend\r\n<\/code><\/pre>\n<p>This is the most common way to sequence events. You can tell what the control flow is just by reading a cookbook from top to bottom.<\/p>\n<h2>Notify resources about changes<\/h2>\n<p>Chef provides a notification mechanism for signaling when things change. This lets you do things like restart a service when a configuration file changes. Want to lay down your own NTP configuration file and bounce the service when it\u2019s updated? Easy. Have your <a title=\"Various (Opscode): The is used to manage file contents with an embedded Ruby (erb) template.\" href=\"http:\/\/docs.opscode.com\/chef\/resources.html#template\">template resource<\/a> notify your <a title=\"Various (Opscode): The service resource is used to manage a service.\" href=\"http:\/\/docs.opscode.com\/chef\/resources.html#service\">service resource<\/a> of the change.<\/p>\n<pre><code>template '\/etc\/ntp.conf' do\r\n  notifies :restart, 'service[ntp]'\r\nend\r\n\r\nservice 'ntp' do\r\n  action :start\r\nend\r\n<\/code><\/pre>\n<p>Something that surprised me when I first started working with Chef, was that notifications on resources queue, then trigger at the end of the run. So the recipe above takes the following actions:<\/p>\n<ol>\n<li>Updates the template.<\/li>\n<li>Queues a restart of the service.<\/li>\n<li>Starts the service.<\/li>\n<li>Restarts the service.<\/li>\n<\/ol>\n<p>Sometimes you want a notification to trigger right after something changes, instead of waiting until the end of the run. In that case, you can use the <code>:immediately<\/code> flag.<\/p>\n<pre><code>template '\/etc\/ntp.conf' do\r\n  notifies :restart, 'service[ntp]', :immediately\r\nend\r\n\r\nservice 'ntp' do\r\n  action :start\r\nend\r\n<\/code><\/pre>\n<h2>Check if resources have changed<\/h2>\n<p>Chef resources are first class objects, which means you can ask them about their state during the run. Every resource has an <code>updated_by_last_action?<\/code> method which returns <code>true<\/code> if the resource changed. Combining this with sequential execution lets you build robust cookbooks.<\/p>\n<p>Suppose you want to download and unpack a tarball. If the folder you\u2019re unpacking into exists, you\u2019ll want to remove it first. But if the tarball hasn\u2019t changed, you\u2019ll want to skip that step. Download the package with a <a title=\"Various (Opscode): The remote_file resource is used to transfer a file from a remote location.\" href=\"http:\/\/docs.opscode.com\/chef\/resources.html#remote-file\">remote file resource<\/a> resource, cache the result, and use the <code>only_if<\/code>modifier on a <a title=\"Various (Opscode): The directory resource is used to manage a directory, which is a hierarchy of folders that comprises all of the information stored on a computer.\" href=\"http:\/\/docs.opscode.com\/chef\/resources.html#directory\">directory resource<\/a> to skip the removal if the tarball\u2019s unchanged.<\/p>\n<pre><code>tarball = remote_file '~\/node-v0.8.20.tar.gz' do\r\n  source 'http:\/\/nodejs.org\/dist\/v0.8.20\/node-v0.8.20.tar.gz'\r\nend\r\n\r\nfolder = directory '~\/node-v0.8.20' do\r\n  action :remove\r\n  only_if { tarball.updated_by_last_action? }\r\nend<\/code><\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>for config in [ &#8220;contacts.cfg&#8221;, &#8220;contactgroups.cfg&#8221; ] do remote_file &#8220;\/etc\/nagios3\/#{config}&#8221; do source &#8220;#{config}&#8221; owner &#8220;root&#8221; group &#8220;root&#8221; mode 0644 notifies :restart, resources(:service =&gt; &#8220;nagios&#8221;), :delayed end end Write it in the order you want it to run <\/p>\n<p>Chef executes resources in the order they appear in a recipe. Coming to Chef from Puppet, I found [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[80],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/6540"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6540"}],"version-history":[{"count":1,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/6540\/revisions"}],"predecessor-version":[{"id":6541,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/6540\/revisions\/6541"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}