PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/blog/public/blog/2011/06/24/59995517/index.html

https://github.com/sbates/Bratty-Redhead
HTML | 294 lines | 182 code | 108 blank | 4 comment | 0 complexity | f715218f07dfb7c429a687ef7a7e2a16 MD5 | raw file
  1. <!DOCTYPE html>
  2. <!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
  3. <!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
  4. <!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
  5. <head>
  6. <meta charset="utf-8">
  7. <title>My ohai plugin - WYSIWYG</title>
  8. <meta name="author" content="Sascha Bates">
  9. <meta name="description" content="The plugin at github When we started the Chef infrastructure automation project last year, a dev team started up at nearly the same time.&nbsp; I &hellip;">
  10. <!-- http://t.co/dKP3o1e -->
  11. <meta name="HandheldFriendly" content="True">
  12. <meta name="MobileOptimized" content="320">
  13. <meta name="viewport" content="width=device-width, initial-scale=1">
  14. <link rel="canonical" href="http://brattyredhead.com/blog/2011/06/24/59995517">
  15. <link href="/favicon.png" rel="icon">
  16. <link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
  17. <script src="/javascripts/modernizr-2.0.js"></script>
  18. <script src="/javascripts/ender.js"></script>
  19. <script src="/javascripts/octopress.js" type="text/javascript"></script>
  20. <link href="/atom.xml" rel="alternate" title="WYSIWYG" type="application/atom+xml">
  21. <!--Fonts from Google"s Web font directory at http://google.com/webfonts -->
  22. <link href="http://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
  23. <link href="http://fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
  24. </head>
  25. <body >
  26. <header role="banner"><hgroup>
  27. <h1><a href="/">WYSIWYG</a></h1>
  28. <h2>no subtext here</h2>
  29. </hgroup>
  30. </header>
  31. <nav role="navigation"><ul class="subscription" data-subscription="rss">
  32. <li><a href="/atom.xml" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
  33. </ul>
  34. <form action="http://www.duckduckgo.com/" method="get">
  35. <fieldset role="search">
  36. <input type="hidden" name="q" value="site:brattyredhead.com" />
  37. <input class="search" type="text" name="q" results="0" placeholder="Search"/>
  38. </fieldset>
  39. </form>
  40. <ul class="main-navigation">
  41. <li><a href="/">Blog</a></li>
  42. <li><a href="/blog/archives">Archives</a></li>
  43. </ul>
  44. </nav>
  45. <div id="main">
  46. <div id="content">
  47. <div>
  48. <article class="hentry" role="article">
  49. <header>
  50. <h1 class="entry-title">My Ohai Plugin</h1>
  51. <p class="meta">
  52. <time datetime="2011-06-24T00:00:00-05:00" pubdate data-updated="true">Jun 24<span>th</span>, 2011</time>
  53. </p>
  54. </header>
  55. <div class="entry-content"><p><a href="https://github.com/sbates/Chef-odds-n-ends/blob/master/ohai/parse_host_plugin.rb" title="The plugin at github" target="_blank">The plugin at github</a></p>
  56. <p>When we started the Chef infrastructure automation project last year, a dev team started up at nearly the same time.&nbsp; I didn&#8217;t know enough about Chef to have (much of) an opinion on how others were addressing cookbook issues they faced. So for the first few months, I worked on my problems to solve while the devs worked on theirs.&nbsp; I did eventually started paying attention to what was going on with the dev team and discovered that they had started to create role names that looked like app_name_env(e.g. riak_prod), causing a role for each app to be created in each environment, but with nearly identical run lists.&nbsp; They were labeling their attributes with environment and used the roles to sort them out.</p>
  57. <p>So we came up with a quick solution.&nbsp; We created an attribute called node[:env] and put it in a role called env_dev, env_qa, etc.&nbsp; And the same goes for other things we needed to set like node[:swimlane] and node[:zone]. Every time a node was created, relevant env attribute roles were added along with the platform_base and any application roles.&nbsp; We all refactored our code and started using the env variable to sort out environment-specific attributes. This worked well in the short term, for about 6 months.</p>
  58. <p>About 2 months ago, we started planning for provisioning a second data center.&nbsp; With another data center containing two environments (prod and stage) came a location issue.&nbsp; Now we have two sets of ntp servers, different DNS servers and a whole host of location-specific coding issues. I went to go add some location-specific roles and started thinking about the refactoring we&rsquo;d need to do to account for two locations.</p>
  59. <p>As I started to make the first role, I realized that this was quickly becoming an unwieldy solution.&nbsp; We were configuring the nodes managed by our automation system <strong>by hand</strong>.&nbsp; This boggled me. And the number of managed nodes continues to grow.</p>
  60. <p>&nbsp;</p>
  61. <p>One of the problems we struggle with is that we have no system of record.&nbsp; We get most of our new server info on spreadsheets from various project teams or ops/mgmt teams.&nbsp; We can&rsquo;t call any central system API to get info. &nbsp;All the servers have static IPs and minimum of two networks. The ops team doesn&rsquo;t believe in DNS. So we have to keep all of this information somewhere or figure out clever ways to deduce the information we want (or set roles by hand, ugh!).</p>
  62. <p>A secondary problem I had with the roles is that their attributes weren&rsquo;t set early enough for me to use logic in the attributes file.&nbsp; Node[:env] didn&rsquo;t get set until after attributes files were compile which was causing me other problems.</p>
  63. <p>So as I thought about the location role, I rebelled.&nbsp; I was <strong>done</strong> setting roles by hand.&nbsp; UGH!</p>
  64. <p>All of our host names are the same length and contain a rich amount of data encoded in their names.&nbsp; I thought that there must be a way to extract and label that information for use as node attibutes.&nbsp; I&rsquo;m no Ruby genius and I still struggle with anything beyond fancy scripting, but it&rsquo;s extra fun for me to run at a problem head on and obsess over it. And that&rsquo;s what I did.&nbsp;</p>
  65. <p>When I came out of the weekend, I had an oHai plugin that parsed a host name, set 3 top level attributes and 5 nested attributes thatI thought might be useful for logic in cookbooks.&nbsp; It looks like this:</p>
  66. <p>[root@pxqpkyapp05 tmp]# ohai -f /tmp/plugins/parse_host_plugin.rb&nbsp; -l debug<br /> [Fri, 24 Jun 2011 19:09:09 -0500] DEBUG: ohai plugin: parse_host: parsing new host pxqpkyapp05<br /> {</p>
  67. <p><strong>&nbsp; &#8220;environment&#8221;: &#8220;qa&#8221;</strong><br /> <strong>&nbsp; &#8220;location&#8221;: &#8220;pismo&#8221;,</strong><br /> &nbsp; &#8220;hostdata&#8221;: {<br /> &nbsp;&nbsp;&nbsp; &#8220;server_type&#8221;: &#8220;application&#8221;,<br /> &nbsp;&nbsp;&nbsp; &#8220;loc&#8221;: &#8220;p&#8221;,<br /> &nbsp;&nbsp;&nbsp; &#8220;env&#8221;: &#8220;q&#8221;,<br /> &nbsp;&nbsp;&nbsp; &#8220;application&#8221;: &#8220;Pooky&#8221;,<br /> &nbsp;&nbsp;&nbsp; &#8220;platform&#8221;: &#8220;solaris&#8221;<br /> &nbsp; },<br /> }<br /> </p>
  68. <p>I didn&rsquo;t think this would be useful to anyone but us.&nbsp; Surely everyone else was using Chef in the cloud, right?&nbsp; Heck no.&nbsp; It turns out, as I was chatting with folks at Velocity last week, that several people are data center-bound with encoded host names.&nbsp; Discussing it, I thought it might be useful to share, even if it would require some tweaking to make it work with any else&rsquo;s environment.</p>
  69. <p>Basically, I set a hash with environment data and then set variables using a regex on the host name.&nbsp; I set the environment and location vars separately and then put indexes in the hash for any values I want to add into the hostdata hash.&nbsp; I took most of our custom logic out, like the node[:zone] logic that no one needs, although I left in a custom piece I had to add for an oddly named environment at a third data center location.&nbsp; All app names and locations have been changed to protect the innocent (that&rsquo;s me).</p>
  70. <p>I hope someone else can use it.&nbsp; It was my first step beyond recipes and I&rsquo;m rather proud of it. I&#8217;ve already had a request from a team mate to move the logic to a library so that we can use it in our host management activities and that&#8217;s what I&#8217;m working on now.&nbsp; I&#8217;ve created a class and a function that uses the class, but need to translate it to Chef-specific DSL.</p>
  71. <p>Here are some examples of how we&#8217;re using them:</p>
  72. <p>&nbsp;</p>
  73. <p>in the recipe: dnsinfo = search(:dns, &#8220;id:#{node.location}&#8221;)</p>
  74. <p>in the template:</p>
  75. <p>domain &lt;%= @dnsinfo[&#8220;domain&#8221;] %&gt;<br />search &lt;%= @dnsinfo[&#8220;search&#8221;] %&gt;<br />&lt;% @dnsinfo[&#8220;nameservers&#8221;].each do |ns| %&gt;<br />nameserver &lt;%= ns %&gt;<br />&lt;% end %&gt;</p>
  76. <p># Unload unwanted packages<br />unless node.env == &#8220;dev&#8221; || node.attribute?(&#8220;keep_gcc&#8221;)<br />&nbsp;package &#8220;gcc&#8221; do<br />&nbsp;&nbsp; action :remove<br />&nbsp;end<br />end<p /></p>
  77. <p>chefsearch = search(&#8220;chef_servers&#8221;,&#8221;env:#{node.env} AND id:#{node.hostdata.loc}*&#8221;).first<br />node.set.chef.my_chef_server = chefsearch[&#8220;id&#8221;]</p>
  78. <p>node.set.chef.server_url = &#8220;http://#{node.chef.my_chef_server}&#8221;<br />node.set.chef.mrepo_url = &#8220;http://#{node.chef.my_chef_server}/mrepo&#8221;<br />node.set.chef.proxy_url = &#8220;http://#{node.chef.my_chef_server}:8000&#8221;</p>
  79. <p>&nbsp;</p>
  80. <p>This will also come in handy once we&#8217;ve migrated to .10 where we can set so many more things within Chef based on environment.&nbsp; The plugin is phrased in functions as my original plugin file was rather messy with comments and things.&nbsp; I felt like breaking it down this way made it easier to follow wth was going on.</p>
  81. <p>Please let me know if you find this useful or if you have questions.&nbsp; This is my first community contribution and so I&#8217;m kind of like the kid with the cool shiny thing they want to show everyone.&nbsp; Look at my shiny!</p>
  82. </div>
  83. <footer>
  84. <p class="meta">
  85. <span class="byline author vcard">Posted by <span class="fn">Sascha Bates</span></span>
  86. <time datetime="2011-06-24T00:00:00-05:00" pubdate data-updated="true">Jun 24<span>th</span>, 2011</time>
  87. </p>
  88. <div class="sharing">
  89. <a href="http://twitter.com/share" class="twitter-share-button" data-url="http://brattyredhead.com/blog/2011/06/24/59995517/" data-via="sascha_d" data-counturl="http://brattyredhead.com/blog/2011/06/24/59995517/" >Tweet</a>
  90. </div>
  91. <p class="meta">
  92. <a class="basic-alignment left" href="/blog/2011/06/23/another-chapter-done/" title="Previous Post: Another Chapter Done">&laquo; Another Chapter Done</a>
  93. <a class="basic-alignment right" href="/blog/2011/06/24/reason-eleventyseven-to-automate/" title="Next Post: Reason #eleventyseven to automate">Reason #eleventyseven to automate &raquo;</a>
  94. </p>
  95. </footer>
  96. </article>
  97. </div>
  98. <aside class="sidebar">
  99. <section>
  100. <h1>About Me</h1>
  101. <p>A little something about me.</p>
  102. </section>
  103. <section>
  104. <h1>Recent Posts</h1>
  105. <ul id="recent_posts">
  106. <li class="post">
  107. <a href="/blog/2012/05/27/finding-sanity-with-chef/">Finding Sanity With Chef</a>
  108. </li>
  109. <li class="post">
  110. <a href="/blog/2012/05/08/test/">test</a>
  111. </li>
  112. <li class="post">
  113. <a href="/blog/2012/04/27/my-favorite-jvm-arg-ever/">My Favorite JVM Arg EVER</a>
  114. </li>
  115. <li class="post">
  116. <a href="/blog/2012/04/26/the-alien-technology-tuning-challenge/">The Alien Technology Tuning Challenge</a>
  117. </li>
  118. <li class="post">
  119. <a href="/blog/2012/04/15/yak-hacking/">Yak Hacking - A Story</a>
  120. </li>
  121. <li class="post">
  122. <a href="/blog/2012/04/01/weekend-chef-and-puppet-projects/">Weekend Chef and Puppet Projects</a>
  123. </li>
  124. <li class="post">
  125. <a href="/blog/2012/03/26/annoying-recruiter-call-45/">Annoying Recruiter Call #45</a>
  126. </li>
  127. <li class="post">
  128. <a href="/blog/2012/03/23/i-am-not-a-fangirl/">I am not a fangirl</a>
  129. </li>
  130. <li class="post">
  131. <a href="/blog/2011/11/19/puppet-for-chef-users-part-2-when-is-a-node-a/">Puppet for Chef Users - Part 2 - When is a node a node? </a>
  132. </li>
  133. <li class="post">
  134. <a href="/blog/2011/11/07/puppet-for-chef-users/">Puppet for Chef Users</a>
  135. </li>
  136. </ul>
  137. </section>
  138. <section>
  139. <h1>Latest Tweets</h1>
  140. <ul id="tweets">
  141. <li class="loading">Status updating...</li>
  142. </ul>
  143. <script type="text/javascript">
  144. $.domReady(function(){
  145. getTwitterFeed("sascha_d", 4, false);
  146. });
  147. </script>
  148. <script src="/javascripts/twitter.js" type="text/javascript"> </script>
  149. <a href="http://twitter.com/sascha_d" class="twitter-follow-button" data-show-count="false">Follow @sascha_d</a>
  150. </section>
  151. <section>
  152. <h1>My Pinboard</h1>
  153. <ul id="pinboard_linkroll">Fetching linkroll...</ul>
  154. <p><a href="http://pinboard.in/u:sascha_d">My Pinboard Bookmarks &raquo;</a></p>
  155. </section>
  156. <script type="text/javascript">
  157. var linkroll = 'pinboard_linkroll'; //id target for pinboard list
  158. var pinboard_user = "sascha_d"; //id target for pinboard list
  159. var pinboard_count = 3; //id target for pinboard list
  160. (function(){
  161. var pinboardInit = document.createElement('script');
  162. pinboardInit.type = 'text/javascript';
  163. pinboardInit.async = true;
  164. pinboardInit.src = '/javascripts/pinboard.js';
  165. document.getElementsByTagName('head')[0].appendChild(pinboardInit);
  166. })();
  167. </script>
  168. </aside>
  169. </div>
  170. </div>
  171. <footer role="contentinfo"><p>
  172. Copyright &copy; 2012 - Sascha Bates -
  173. <span class="credit">Powered by <a href="http://octopress.org">Octopress</a></span>
  174. </p>
  175. </footer>
  176. <script type="text/javascript">
  177. (function(){
  178. var twitterWidgets = document.createElement('script');
  179. twitterWidgets.type = 'text/javascript';
  180. twitterWidgets.async = true;
  181. twitterWidgets.src = 'http://platform.twitter.com/widgets.js';
  182. document.getElementsByTagName('head')[0].appendChild(twitterWidgets);
  183. })();
  184. </script>
  185. </body>
  186. </html>