<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><description>Automating my team so we can build better things</description><title>Tyler Fitch</title><generator>Tumblr (3.0; @tfitch)</generator><link>http://www.tfitch.com/</link><item><title>Searching by a Node's cookbook's attributes</title><description>&lt;p&gt;We&amp;#8217;re working on a method for self discovery of a group of servers being setup to be a MongoDB replica set.  And a specific replica set among an environment with multiple MongoDB servers and replica sets at that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; A cookbook&amp;#8217;s node attributes are uploaded back to the server and available to be searched against.  &lt;span&gt;Here&amp;#8217;s the secret to searching on the Node&amp;#8217;s attributes defined in the cookbook.  In the cookbook we had node[&amp;#8216;mongodb&amp;#8217;][&amp;#8216;replica_set&amp;#8217;] but when we wanted to search for it we did mongodb_replica_set:ReplSet1 - chaining the full name of the attributes with underscores.  Doesn&amp;#8217;t entirely seem intuitive, but it is the way Search works.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Out of all the servers in a Chef server Organization we&amp;#8217;re going to use three keys to identify the machines of a single replica set.&lt;/p&gt;
&lt;p&gt;1) A Role - &lt;a href="http://www.getchef.com/blog/2013/11/19/chef-roles-arent-evil/" title="Chef Roles" target="_blank"&gt;http://www.getchef.com/blog/2013/11/19/chef-roles-arent-evil/&lt;/a&gt; For this I like having two roles, mongodb-primary and mongodb-secondary.  The difference will be the run_list.  Both will have the recipe[&amp;#8216;mongodb&amp;#8217;] which will install, configure and startup MongoDB on the servers.  But the mongodb-primary role will have the run_list of recipe[&amp;#8216;mongodb&amp;#8217;],recipe[&amp;#8216;mongodb::primary&amp;#8217;] to install MongoDB and configure the replicaset.&lt;/p&gt;
&lt;p&gt;2) The Environment - &lt;a href="https://docs.getchef.com/essentials_environments.html" title="Chef Environments" target="_blank"&gt;https://docs.getchef.com/essentials_environments.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;3) A replica set name, set via a cookbook attribute &lt;code&gt;default['mongodb']['replica_set'] = 'ReplSet1'&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Not everyone in the Chef community may love Roles and Environments, but this is a great use case for them.  Treating the combination of the three like a compound key in a database table, we&amp;#8217;re able to identify like machines to be joined together in to the replica set.&lt;/p&gt;
&lt;p&gt;Searching for the Nodes&lt;/p&gt;
&lt;p&gt;Using the above three values, what do the search commands look like?  First up from knife we&amp;#8217;d have&lt;/p&gt;
&lt;script src="https://gist.github.com/tfitch/bc6e46d279e78f3af93d.js" type="text/javascript"&gt;&lt;/script&gt;&lt;p&gt;This is nice to verify you&amp;#8217;ll get the desired search results without having to run a cookbook and debug the search syntax by doing a node converge.&lt;/p&gt;
&lt;p&gt;Now we&amp;#8217;ve got the search syntax worked out, we&amp;#8217;ll want to actually use this in a cookbook to create a replicaset configuration file.&lt;/p&gt;
&lt;script src="https://gist.github.com/tfitch/0d3e7b610471d2f175b3.js" type="text/javascript"&gt;&lt;/script&gt;&lt;script src="https://gist.github.com/tfitch/1d346c8631b68ddb1fdd.js" type="text/javascript"&gt;&lt;/script&gt;&lt;p&gt;There we have it.  We&amp;#8217;ve found all the machines we want to be in the same replicaset and configured the replicaset by running the JS file on the Primary machine of the MongoDB replica set.&lt;/p&gt;
&lt;p&gt;Remember, only one machine in the replica sets needs to run this script, the primary.  &lt;strong&gt;AND&lt;/strong&gt; it will need to run it last, after all the nodes in the replicaset are running (you can&amp;#8217;t add a machine to a replica set if it isn&amp;#8217;t running and configured to be a mongodb yet).&lt;/p&gt;</description><link>http://www.tfitch.com/post/96763217143</link><guid>http://www.tfitch.com/post/96763217143</guid><pubDate>Fri, 05 Sep 2014 22:15:27 -0700</pubDate><category>opschef</category><category>mongodb</category></item><item><title>Sending name/value pairs from Chef cookbook attributes to be dynamic Resource attributes</title><description>&lt;p class="p1"&gt;One of my customers had a question about using name/value pairs from his cookbook&amp;#8217;s attributes as settings for a Resource.&lt;/p&gt;
&lt;p class="p1"&gt;TL;DR - The name/value pairs in a cookbook Resource object are more than just a combination of attribute + value. More precisely, they&amp;#8217;re a method_name + value combination. So making the method_name come from a dynamic source requires you use &lt;code&gt;send()&lt;/code&gt; method of a Ruby Object to invoke the method, not just output a String equal to what the cookbook would look like if everything was hard coded.&lt;/p&gt;
&lt;p class="p1"&gt;Long form:&lt;/p&gt;
&lt;p class="p1"&gt;Let&amp;#8217;s start with the hardcoded cookbook recipe and see what that would look like.&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/tfitch/d5cd2954e0d052cd7a44.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p class="p1"&gt;Now to convert all those Resource attributes to be dynamic let&amp;#8217;s convert them in to Attributes of the cookbook&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/tfitch/806d083ea44f068a0d0f.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p class="p1"&gt;A first attempt at setting the attributes looked liked this, but it did not work&lt;/p&gt;
&lt;script src="https://gist.github.com/tfitch/b7f4226988300b67df2f.js" type="text/javascript"&gt;&lt;/script&gt;&lt;p class="p1"&gt;At first pass this all looked correct to me too. I was stumped until my brilliant co-worker Steve Danna (&lt;a href="https://twitter.com/stevedanna" target="new"&gt;@SteveDanna&lt;/a&gt;) shared some great Ruby/Chef knowledge with me. The correct way to achieve the goal would be this&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/tfitch/3d21d18ca4e859b59ab7.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p class="p1"&gt;The key here is the &lt;code&gt;send()&lt;/code&gt; method. &lt;a href="http://ruby-doc.org/core-2.1.2/Object.html#method-i-send" target="_new"&gt;http://ruby-doc.org/core-2.1.2/Object.html#method-i-send&lt;/a&gt;&lt;/p&gt;
&lt;p class="p1"&gt;When you do &lt;code&gt;#{setting} #{value}&lt;/code&gt; then &lt;code&gt;setting&lt;/code&gt; is just returned as a string and not *calling* the relevant setter method of the Resource object (iis_pool in this case).&lt;/p&gt;
&lt;p class="p1"&gt;I guess this surprised me, because when the cookbook is hardcoded you see the line &lt;code&gt;thirty_two_bit false&lt;/code&gt; and it reads like two strings and not that &lt;code&gt;thirty_two_bit&lt;/code&gt; is actually a method name being called.&lt;/p&gt;
&lt;p class="p1"&gt;Alas, now I know and you do too.&lt;/p&gt;</description><link>http://www.tfitch.com/post/96390450853</link><guid>http://www.tfitch.com/post/96390450853</guid><pubDate>Mon, 01 Sep 2014 14:05:00 -0700</pubDate><category>opschef</category><category>chef</category></item><item><title>#ChefConf 2014 BoF - Creating Deploy Jobs in Jenkins</title><description>&lt;p class="p1"&gt;At #ChefConf 2014 I had the honor of leading a Birds of a Feather session on &amp;#8220;Creating Deploy Jobs in Jenkins&amp;#8221;.&lt;/p&gt;
&lt;p class="p1"&gt;&lt;img src="https://31.media.tumblr.com/e708a8b164e807d14e3115951221f51f/tumblr_inline_n4swseWV8v1qz7nql.jpg"/&gt;&lt;/p&gt;

&lt;p class="p1"&gt;My interest here is in deploying a web app to my Chef managed servers.  The problem I need to solve is for when you don&amp;#8217;t know what servers you have because in the Cloud the servers come and go.  &lt;a href="http://www.theregister.co.uk/2013/03/18/servers_pets_or_cattle_cern/" target="_blank"&gt;Servers are cattle - not pets, right?&lt;/a&gt;&lt;/p&gt;
&lt;p class="p1"&gt;&lt;strong&gt;So what are our options?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Doing it manually - bleh: &lt;/strong&gt;Hardcoding server addresses in a Jenkins deploy job won&amp;#8217;t work.  Well, it&amp;#8217;ll work until you shoot your cow and spin up a new one.  Manually updating the Jenkins deploy job with the current server addresses sounds about as fun as herding cats and won&amp;#8217;t help you &lt;a href="https://www.amazon.com/gp/product/0321601912/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0321601912&amp;amp;linkCode=as2&amp;amp;tag=tylfit-20" target="_blank"&gt;Continuously Deliver&lt;/a&gt;.&lt;/p&gt;
&lt;p class="p1"&gt;&lt;span&gt;&lt;strong&gt;Use the Chef Server &lt;/strong&gt;+ &lt;/span&gt;&lt;em&gt;knife status&lt;/em&gt;&lt;span&gt; to lookup what servers you have.  When combined with roles + environments, this gets an accurate reading of what&amp;#8217;s out there to deploy to.  I&amp;#8217;ve found the output of &lt;em&gt;knife status&lt;/em&gt; is also much friendlier to command-line fu than the &lt;em&gt;knife search&lt;/em&gt; output.&lt;/span&gt;&lt;/p&gt;
&lt;p class="p2"&gt;&lt;em&gt;knife status &amp;#8220;role:webserver AND chef_environment:stage&amp;#8221;&lt;/em&gt; will give me the following output.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;12 mins ago, ec2-57.186.102.29-1396555868.17, ec2-57-186-102-29.us-west-2.compute.amazonaws.com, 192.31.9.43, centos 6.4.&lt;br/&gt;8 mins ago, ec2-57.82.206.136-1396555883.36, ec2-57-82-206-136.compute-1.amazonaws.com, 57.82.206.136, centos 6.4.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class="p1"&gt;So I want to cherry pick the 3rd item of the comma-separated list, the hostname.  I could use &lt;em&gt;awk&lt;/em&gt;, but found a simple example using &lt;em&gt;cut&lt;/em&gt; and went with it.&lt;/p&gt;
&lt;p class="p1"&gt;I loop over the output of the knife status search like so&lt;/p&gt;
&lt;p class="p2"&gt;&lt;em&gt;for h in $(knife status &amp;#8220;role:webserver AND chef_environment:load&amp;#8221;| cut -d&amp;#8217;,&amp;#8217; -f3); do ssh -oStrictHostKeyChecking=no myuser@$h &amp;#8220;uptime&amp;#8221;; done&lt;/em&gt;&lt;/p&gt;
&lt;p class="p1"&gt;The &lt;em&gt;-oStrictHostKeyChecking=no&lt;/em&gt; is there because I&amp;#8217;ve maybe never deployed to this cow before.  Change the &lt;em&gt;ssh &amp;#8220;uptime&amp;#8221;&lt;/em&gt; command to the necessary &lt;em&gt;scp&lt;/em&gt; command and you&amp;#8217;re deploying.&lt;/p&gt;
&lt;p class="p2"&gt;&lt;span&gt;But it isn&amp;#8217;t bulletproof.  If a server crashes and doesn&amp;#8217;t unregister itself as an active node with the Chef server you&amp;#8217;ll try to deploy to a place that is no longer valid.  One way to mitigate this is use the timestamp column in the `knife status` result that shows the last time the server phoned home.  If all servers are checking in every 15-30 mins and it&amp;#8217;s been an hour since the Chef client last checked with the Chef server then skip trying to deploy to it.&lt;/span&gt;&lt;/p&gt;
&lt;p class="p2"&gt;&lt;strong&gt;&lt;span&gt;Amazon AWS API options:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p class="p2"&gt;&lt;span&gt;During the discussion two options for Amazon Web Services were identified.  First up, use the AWS API to query for the list of active servers to deploy to.  If you tag them or have other means to identify their role in your infrastructure you&amp;#8217;ll know what&amp;#8217;s active at that time.  I imagine other cloud hosting providers will have similar APIs available.  Secondly, &lt;a href="https://twitter.com/kennonkwok" target="_blank"&gt;Kennon Kwok&lt;/a&gt; &lt;/span&gt;&lt;span&gt;from Chef tipped me off to a nice library from Netflix called &lt;/span&gt;&lt;a href="https://github.com/Netflix/edda/wiki" target="_blank"&gt;Edda&lt;/a&gt;&lt;span&gt; which &amp;#8220;polls your AWS resources via AWS APIs and records the results. It allows you to quickly search through your resources and show how they have changed over time.&amp;#8221;  In other words, Edda is wrapper for the AWS API that adds in historical data too (among other things).  Nice. &lt;/span&gt;&lt;/p&gt;
&lt;p class="p1"&gt;Both of these options are nice a would be more accurate than polling the Chef server.  But in my environment I actually have a tool called &lt;a href="http://www.scalr.com/" target="_blank"&gt;Scalr&lt;/a&gt; fronting my AWS account.  So I can create servers but do not actually have the account&amp;#8217;s AWS secret key use the AWS API or Edda!  It&amp;#8217;s a hard knock life in the corporate world of cloud billing and measures to consolidate billing for their numerous AWS accounts.&lt;/p&gt;
&lt;p class="p2"&gt;&lt;strong&gt;&lt;span&gt;Lesser known options:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p class="p2"&gt;&lt;span&gt;Also discussed were the ideas of using &lt;a href="http://zookeeper.apache.org/" target="_blank"&gt;Apache Zookeeper&lt;/a&gt;&lt;/span&gt;, &lt;a href="http://www.serfdom.io/" target="_blank"&gt;Serf from Hashicorp&lt;/a&gt; or &lt;a href="https://github.com/coreos/etcd" target="_blank"&gt;etcd from CoreOS&lt;/a&gt;.  Zookeeper was not highly rated for WAN setups with machines not on the same networks.  And there was not enough experience with Serf or etcd in the room to give them a proper evaluation. &lt;/p&gt;
&lt;p class="p2"&gt;&lt;strong&gt;&lt;span&gt;The end result for me?&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p class="p2"&gt;&lt;span&gt;I&amp;#8217;m still proceeding with my initial plan that uses Chef Server + &lt;em&gt;knife status&lt;/em&gt; lookup command, but now know a few more options to use in the future to solve to create my deployment jobs in Jenkins.&lt;/span&gt;&lt;/p&gt;
&lt;p class="p2"&gt;&lt;span&gt;Thanks to Kennon, Eric from Boston, Mahesh from Dow Jones, the Behance guys and the others that I didn&amp;#8217;t get your names but joined in the conversation for the BoF.  I had a great time and hope you all did too.&lt;/span&gt;&lt;/p&gt;</description><link>http://www.tfitch.com/post/84205085988</link><guid>http://www.tfitch.com/post/84205085988</guid><pubDate>Mon, 28 Apr 2014 23:29:00 -0700</pubDate></item><item><title>Installing Sun Java 1.5 with Chef</title><description>&lt;p&gt;In trying to use the &lt;a href="http://community.opscode.com/cookbooks/java" target="_blank"&gt;Opscode Chef community cookbook for Java&lt;/a&gt; I found it to only work with Java 6 and Java 7.&lt;/p&gt;
&lt;p&gt;In trying to create a script to recreate an existing environment I need a scripted install of the &lt;a href="http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase5-419410.html" target="_blank"&gt;Sun 1.5 JDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So I had to bail entirely on the community cookbook and go my own route.  Here&amp;#8217;s how it played out.&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Download the installer you need.  In my case the .bin file - without the rpm, just the bin.&lt;/li&gt;
&lt;li&gt;Upload the .bin to your &lt;a href="http://www.jfrog.com/home/v_artifactory_opensource_overview" target="_blank"&gt;Artifactory &lt;/a&gt;server so everyone can easily get access to it when building their VMs.&lt;/li&gt;
&lt;li&gt;Get the installer on to the VM using Chef &lt;em&gt;remote_file &lt;/em&gt;command with &lt;em&gt;mode 0700&lt;/em&gt; to ensure the installer is executable. &lt;br/&gt;&lt;script src="https://gist.github.com/tfitch/5889761.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/li&gt;
&lt;li&gt;Run the bash command to run the installer &lt;br/&gt; The installer requires acceptance of the EULA. So scripting this was a pain. Hat tip to Kule on linuxquestions.com - &lt;a href="http://www.linuxquestions.org/questions/linux-newbie-8/java-jdk-silent-install-help-891313/#post4433389" target="_blank"&gt;http://www.linuxquestions.org/questions/linux-newbie-8/java-jdk-silent-install-help-891313/#post4433389&lt;/a&gt; &lt;br/&gt; The EOH here is important - EOF did not work nor the &lt;em&gt;command&lt;/em&gt; attribute. &lt;br/&gt;&lt;script src="https://gist.github.com/tfitch/5889768.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/li&gt;
&lt;li&gt;Create a environment variables $JAVA_HOME just like the Java cookbook would and many Java apps now expect to exist. &lt;br/&gt;&lt;script src="https://gist.github.com/tfitch/5889735.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;One thing this does not do is put the java and/or javac executables in to your $PATH.  I&amp;#8217;d do this like the Java cookbook does and do symlinks to /usr/local/bin if you need it.&lt;/p&gt;</description><link>http://www.tfitch.com/post/54155766792</link><guid>http://www.tfitch.com/post/54155766792</guid><pubDate>Fri, 28 Jun 2013 21:25:00 -0700</pubDate><category>java</category><category>opschef</category></item></channel></rss>
