<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Engine Yard Blog &#187; geemus (Wesley Beary)</title>
	<atom:link href="http://www.engineyard.com/blog/author/wesleybeary/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.engineyard.com/blog</link>
	<description></description>
	<lastBuildDate>Tue, 07 Feb 2012 19:36:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>fog 1.0 is here!</title>
		<link>http://www.engineyard.com/blog/2011/fog-1-0-is-here/</link>
		<comments>http://www.engineyard.com/blog/2011/fog-1-0-is-here/#comments</comments>
		<pubDate>Fri, 30 Sep 2011 14:00:04 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[fog]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=10685</guid>
		<description><![CDATA[<p><a href="http://www.engineyard.com/blog/wp-content/uploads/hero_fog1.png"><img src="http://www.engineyard.com/blog/wp-content/uploads/hero_fog1.png" alt="" title="hero_fog" width="250" height="193" class="alignright size-full wp-image-10692" /></a>Many good things in life take longer  than expected but in the end are well worth the wait. With the release of fog 1.0 we have a shining example. Begun in mid-2009 and with  more than 2 years in production usage at Engine Yard, fog has seen  240,000 downloads. This is definitely a rock-solid 1.0 that has seen  some real battle testing!</p>
<p>fog is a Ruby gem that allows you to control a  number of cloud infrastructure services through a common API. fog  provides the basis for building applications and cloud platforms that  are infrastructure-independent, abstracting such functions as spinning  up servers, connecting storage, managing DNS, etc. Internally, fog uses  models to represent cloud structures analogously to the way ActiveRecord  represents relational structures. Using fog makes your application or  platform much more easily portable across infrastructures such as  Amazon, Rackspace, and many others.</p>
<p>In addition to Engine Yard, fog is in use at other  platform providers as well as in many core community projects such as  Chef, Puppet, CarrierWave, and Paperclip. fog now supports 18 compute, 5  storage, 9 DNS, 2 CDN, and a variety of other infrastructure services.  With 13 core committers, 121 contributors, and nearly 1,500 watchers,  we're seeing really nice growth in participation and attention.</p>
<p>We believe that this release of fog is a really  important step in making the cloud an easier and more powerful  environment for developers to run great apps. We hope you'll give it a  try, share your feedback, spread the word, and (most importantly) enjoy  some great success with fog.</p>
<p>Get fog with a simple <code>gem install fog</code>. Read docs at <a href="http://fog.io/">fog.io</a>, or grab source off GitHub at <a href="https://github.com/geemus/fog">geemus/fog</a>. Happy fogging!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2011/fog-1-0-is-here/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>fog 2011 Halftime Show</title>
		<link>http://www.engineyard.com/blog/2011/fog-2011-halftime-show/</link>
		<comments>http://www.engineyard.com/blog/2011/fog-2011-halftime-show/#comments</comments>
		<pubDate>Wed, 03 Aug 2011 22:58:50 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[fog]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=9925</guid>
		<description><![CDATA[<p>Everything has been going stunningly for <a>fog</a> this year. Now that we have reached the halfway mark (and 0.10.0), it seems we are overdue for an update.</p>
<h3>Since Last Episode</h3>
<p>[caption id="attachment_9987" align="alignright" width="300" caption="Photo courtesy of flickr user nplove"]<a href="http://www.engineyard.com/blog/wp-content/uploads/halftime.jpg"><img class="size-full wp-image-9987 " src="http://www.engineyard.com/blog/wp-content/uploads/halftime.jpg" alt="" width="300" height="199" /></a>[/caption]</p>
<p>Since the <a href="http://www.engineyard.com/blog/2011/fog-0-7-0-0-6-0-and-0-5-0/">last update</a> in mid-March a lot has changed. A new, stronger focus on documentation has helped clarify things alongside many, many fixes and improvements. In addition to fixing the old stuff we have also added support for a number of new services:</p>
<ul>&nbsp;</p>
<li>AWS Autoscaling was added (<a href="https://github.com/geemus/fog/tree/master/tests/aws/requests/auto_scaling">tests</a>)</li>
<li>AWS CloudWatch was added (<a href="https://github.com/geemus/fog/tree/master/tests/aws/requests/cloud_watch">tests</a>)</li>
<li>AWS Simple Notification Service was added (<a href="https://github.com/geemus/fog/tree/master/tests/aws/requests/sns">tests</a>)</li>
<li>AWS Simple Queue Service was added (<a href="https://github.com/geemus/fog/tree/master/tests/aws/requests/sqs">tests</a>)</li>
<li>DNSMadeEasy DNS service was added (<a href="https://github.com/geemus/fog/blob/master/examples/dns_tests.rb">examples</a>)</li>
<li>Linode Compute was expanded with models (<a href="http://github.com/geemus/fog/blob/master/tests/compute/models">tests</a>)</li>
<li>Ninefold Compute (<a href="http://github.com/geemus/fog/blob/master/tests/compute/models">tests</a>)</li>
<li>Ninefold Storage (<a href="http://github.com/geemus/fog/blob/master/tests/storage/models">tests</a>)</li>
<li>OpenStack Compute Support (utilizing Rackspace Implementation)</li>
<li>OpenStack Rackspace Support (utilizing Rackspace Implementation)</li>
<li>vCloud 1.0 (<a href="http://github.com/geemus/fog/blob/master/tests/compute/models">tests</a>)</li>
</ul>
<h3>Stats</h3>
<p>In addition to the codebase, growth and stability have also dominated the userbase. Since the beginning of the year there have been huge gains across the board. We started the year at 50,000 downloads and have now reached 180,000 downloads. Our 860 followers have increased to 1360, 100 forks to 225, and 40 contributors to 105.<span id="more-9925"></span></p>
<p>The most important change may be the number of commiters. At the start of the year I was the sole committer. Since then I have kept a careful eye out for dedicated contributors. There are now 8 of us. These awesome commiters are: <a href="http://github.com/brianhartsock">Brian Hartsock</a>, <a href="http://github.com/coliver">Christopher Oliver</a>, <a href="http://github.com/dylanegan">Dylan Egan</a>, <a href="http://github.com/henryaddison">Henry Addison</a>, <a href="http://github.com/ktheory">Aaron Suggs</a>, <a href="http://github.com/lstoll">Lincoln Stoll</a>, <a href="http://github.com/luqman">Luqman Amjad</a>, <a href="http://github.com/nightshade427">Nick Ricketts</a>, <a href="http://github.com/redzebra">Nick Osborn</a>, <a href="http://github.com/tokengeek">Paul Thornthwaite</a>. I thank them all and encourage you to do the same (HINT: high fives are awesome).</p>
<h3>fog 2011 World Tour</h3>
<p>I just returned from <a href="http://www.oscon.com/oscon2011/public/schedule/detail/18326">OSCON</a>, but there are still plenty of chances to catch up this year. I'll be speaking at <a href="http://lonestarrubyconf.com/">Lone Star Ruby Conf V</a> August 11-13th, <a href="http://gogaruco.com">Golden Gate Ruby Conference</a> September 16-17th, and <a href="https://thestrangeloop.com/sessions/fog-or-how-i-learned-to-stop-worrying-and-love-cloud">Strange Loop</a> September 18-19th. Finally for the cherry on top of a busy conference season, I'll be attending <a href="http://rubyconf.org">RubyConf</a> September 29-October 1st. So, be sure to find me to help answer fog questions, or to offer high fives.</p>
<h3>NEXT!</h3>
<p>The hits keep coming and I expect we will continue to see new providers appear as new competitors emerge and people become interested in trying the latest and greatest.  Beyond that there is still plenty of work to be done to improve the consistency between some of the providers and consolidating the shared feature set. You can expect more great stuff that you have grown accustomed to, but what else might await?</p>
<p>A lot of that is in your hands.  What other services would you like to see abstracted?  Should there be a CLI?  How about RESTFUL web service?  Should we convert the shindo tests to minitest?  These are just a few of the many questions I am focused on answering as we continue to move the project forward. This is a great time to get involved and cast your vote.  You can find all kinds of information about getting involved on the ever expanding <a href="http://fog.io">fog.io</a>.  Let me know what you think!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2011/fog-2011-halftime-show/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Spinning Up Cloud Compute Instances</title>
		<link>http://www.engineyard.com/blog/2011/spinning-up-cloud-compute-instances/</link>
		<comments>http://www.engineyard.com/blog/2011/spinning-up-cloud-compute-instances/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 21:33:16 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[compute]]></category>
		<category><![CDATA[fog]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=9079</guid>
		<description><![CDATA[<p>[caption id="" align="alignright" width="240" caption="Next-Generation Supercomputer Delivered to NERSC by Lawrence Berkeley National Laboratory, on Flickr"]<a href="http://www.flickr.com/photos/berkeleylab/4025866115/"><img src="http://farm3.static.flickr.com/2586/4025866115_61c45b44f3_m.jpg" alt="Next-Generation Supercomputer Delivered to NERSC" width="240" height="160" /></a>[/caption]</p>
<p>Computation is the lifeblood of the cloud, providing the raw resources for innovation. Unfortunately, with great power comes great <del>responsibility</del> complexity. The actual process of refining these resources into services is serious business, further complicated by the huge variance between offerings. Thankfully flexibility and power no longer have to be out of reach. <a href="https://fog.io">fog</a> simplifies the process of utilizing these resources and smooths the differences between providers so that you can focus on creating the next revolutionary cloud service.</p>
<h3>Installing fog</h3>
<p><a href="https://fog.io">fog</a> is distributed as a RubyGem:</p>
<pre escaped="true">gem install fog</pre>
<p>Or for bundler users, you can add it in your Gemfile:</p>
<pre escaped="true">gem "fog"
</pre>
<p><span id="more-9079"></span></p>
<h3>fog =&gt; Rackspace Cloud Servers</h3>
<p>We can start our exploration of cloud computing with Rackspace's <a href="http://www.rackspacecloud.com/cloud_hosting_products/servers">Cloud Servers</a>. You can sign up <a href="https://www.rackspacecloud.com/signup">here</a> and copy down your api key and username from <a href="https://manage.rackspacecloud.com/APIAccess.do">here</a>. We are about to get into the code samples, so be sure to fill in anything in ALL_CAPS with your own values!</p>
<pre lang="ruby" escaped="true"># create a connection
connection = Fog::Compute.new({
  :provider           =&gt; 'Rackspace',
  :rackspace_username =&gt; RACKSPACE_USERNAME,
  :rackspace_api_key  =&gt; RACKSPACE_API_KEY
})</pre>
<h3>Servers the Rackspace way</h3>
<p>Creating a server on Rackspace is very easy if you are willing to accept the defaults (the smallest server size, using Ubuntu 10.04 LTS).</p>
<pre lang="ruby" escaped="true">server = connection.servers.create</pre>
<p>You can then list your servers to see that it now appears.</p>
<pre lang="ruby" escaped="true">connection.servers</pre>
<p>Or you can fetch the latest data for your server in particular.</p>
<pre lang="ruby" escaped="true">servers.get(server.identity)</pre>
<p>As you might imagine, this is a pretty common use case, so fog simplifies it by providing the `reload` method to refresh the state of a model to the freshest available.</p>
<pre lang="ruby" escaped="true">server.reload</pre>
<p>But this too can get tedious quickly, especially when servers can take several minutes to boot.  Fog uses `wait_for` in cases like this to periodically reload a model until either the block returns true or a timeout occurs (by default the timeout is 600 seconds). We can combine wait_for with `ready?` to check when a server has finished booting without needing to know the specifics of each service.</p>
<pre lang="ruby" escaped="true">server.wait_for { ready? }</pre>
<p>Once we are done with that we can shut it down.</p>
<pre lang="ruby" escaped="true">server.destroy</pre>
<h3>Bootstrap: Servers the fog Way</h3>
<p>Cycling servers is great, but in order to actually ssh to a server on Rackspace you need to place ssh keys (and ideally disable password authentication for root). Rather than worrying about the nitty gritty, we can utilize `bootstrap`.</p>
<pre lang="ruby" escaped="true">server = connection.servers.bootstrap({
  :private_key_path =&gt; '~/.ssh/id_rsa',
  :public_key_path =&gt; '~/.ssh/id_rsa.pub'
})</pre>
<p>Bootstrap will create the server, but it will also make sure that port 22 is open for traffic and has ssh keys setup. In order to get all the pieces put together the server will have to be running, so we can skip checking `ready?` since it should already be true.  Now we can send commands directly to the server.</p>
<pre lang="ruby" escaped="true">server.ssh('pwd')
server.ssh(['pwd', 'whoami'])</pre>
<p>These return an array of results, where each has stdout, stderr and status values so you can check out what your commands accomplished.  Now just shut it down to make sure you don't continue getting charged.</p>
<pre lang="ruby" escaped="true">server.destroy</pre>
<h3>Using Amazon EC2 and fog</h3>
<p>Sign up for an account <a href="http://aws-portal.amazon.com/gp/aws/developer/subscription/index.html?productCode=AmazonEC2">here</a> and copy down your secret access key and access key id from <a href="http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key">here</a>.</p>
<p>First, create a connection with your new account:</p>
<pre lang="ruby" escaped="true">require 'rubygems'
require 'fog'

# create a connection
connection = Fog::Compute.new({
  :provider                 =&gt; 'AWS',
  :aws_secret_access_key    =&gt; YOUR_SECRET_ACCESS_KEY,
  :aws_access_key_id        =&gt; YOUR_SECRET_ACCESS_KEY_ID
})</pre>
<p>With that in hand we are ready to start making EC2 calls!</p>
<p>We should be able to reuse all our old code, except for one small exception.  fog uses the official Canonical Ubuntu image as a default on AWS (<a href="http://cloud.ubuntu.com/ami/">official Canonical Releases</a>). This image uses 'ubuntu' as the username, rather than 'root'.  So the bootstrap call will look slightly different.</p>
<pre lang="ruby" escaped="true">server = connection.servers.bootstrap({
  :private_key_path =&gt; '~/.ssh/id_rsa',
  :public_key_path =&gt; '~/.ssh/id_rsa.pub',
  :username =&gt; 'ubuntu'
})</pre>
<p>Just like on Rackspace, this will boot a server and place our keys so that we can ssh in, run commands and eventually shut down the server with <code>destroy</code>.</p>
<h3>Mocking out Compute</h3>
<p>You can also start any of these scripts with</p>
<pre lang="ruby" escaped="true">Fog.mock!</pre>
<p>or start the fog interactive tool from the command line with</p>
<pre escaped="true">$ FOG_MOCK=true fog</pre>
<p>to run in mock mode. In this mode commands are run as local simulation, so no cloud resources are ever consumed and things operate much faster.  Not everything has mocks written for it, but if you run up against these edges errors will be raised to quickly alert you that you are entering not-yet-mocked territory.  The functionality that has been mocked gets exercised by the same test suite as the real code, so you should feel confident that its behavior should be consistent.</p>
<h3>Cleaning up</h3>
<p>To cover your tracks it is a good idea to check for running servers and shut them down, here is one way you might do that.</p>
<pre lang="ruby" escaped="true">connection.servers.select {|server| server.ready? &amp;&amp; server.destroy}</pre>
<h3>Other Providers</h3>
<p>Rackspace and Amazon are just the tip of the iceberg.  fog also supports compute offerings from BlueBox, Brightbox, Terremark, GoGrid, Linode, Slicehost, Storm on Demand and Voxel.  Once you wrap your head around that you can also check out fog's many supported storage, DNS and other services.  With familiar commands throughout it is easy to pick up and try new services. Quickly your toolbox runneth over and you should have all the power you need to innovate.</p>
<h3>Summary</h3>
<p>Compute can be tricky, but the abstractions in fog make it much easier to get started.  With your servers up and running you can then focus on the task at hand and get some work done.  Congratulations on adding a new tool to your arsenal. Let us know what we can do better.
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2011/spinning-up-cloud-compute-instances/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>fog 0.7.0, 0.6.0 and 0.5.0</title>
		<link>http://www.engineyard.com/blog/2011/fog-0-7-0-0-6-0-and-0-5-0/</link>
		<comments>http://www.engineyard.com/blog/2011/fog-0-7-0-0-6-0-and-0-5-0/#comments</comments>
		<pubDate>Fri, 18 Mar 2011 16:37:05 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[fog]]></category>
		<category><![CDATA[fog 0.7.0]]></category>
		<category><![CDATA[magicruby]]></category>
		<category><![CDATA[MountainWest RubyConf]]></category>
		<category><![CDATA[red dirt rubyconf]]></category>
		<category><![CDATA[ruby nation]]></category>
		<category><![CDATA[silicon valley ruby on rails group]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=8009</guid>
		<description><![CDATA[<p>I've been so busy with all the additions to <a href="http://github.com/geemus/fog">fog</a> and new contributors that I forget to update everybody on how things are going (they are great!). The <a href="http://www.engineyard.com/blog/2011/happy-new-year-and-0-4-0-from-fog/">last post</a> I pushed out coincided with 0.4.0 back around the new year and now I'm back to let you know about all the new goodies that have culminated in 0.7.0.</p>
<h3>Adoption</h3>
<p>Adoption continues at an amazing pace.  We went from 40 contributors two short months ago up to 60, crossed 80,000 downloads from <a href="http://rubygems.org/gems/fog">rubygems.org</a> and 1,000 followers on <a href="http://www.github.com/geemus/fog">github</a> [ed: Wes was very giddy on that day].  All the extra attention has helped to weed out even more bugs and grow the available services to meet ever more diverse use cases.</p>
<h3>New Providers and Services</h3>
<p>Once again, several new services have joined the fog family, as well as a few notable additions to the existing services:</p>
<ul>
<li>AWS Cloudformation basics allow for configuring whole clusters at once (<a href="https://github.com/geemus/fog/blob/master/tests/aws/requests/cloud_formation/stack_tests.rb">tests</a>)</li>
<li>AWS IAM has been fleshed out considerably from it's humble origins in 0.4.0 (<a href="https://github.com/geemus/fog/tree/master/tests/aws/requests/iam">tests</a>)</li>
<li>AWS RDS basics add the ability to manage hosted database servers (<a href="https://github.com/geemus/fog/tree/master/tests/aws/requests/rds">tests</a>)</li>
<li>AWS S3 gained static website support (<a href="https://github.com/geemus/fog/blob/master/tests/storage/requests/aws/bucket_tests.rb#L64">tests</a>)</li>
<li>AWS SES basics support for cloud email delivery (<a href="https://gist.github.com/869995">example</a>)</li>
<li>DNSimple DNS service was added (<a href="https://github.com/geemus/fog/blob/master/examples/dns_tests.rb">examples</a>)</li>
<li>VirtualBox basics support managing local virtual machines (<a href="https://gist.github.com/869891">example</a>)</li>
<li>Voxel Compute service was added (<a href="https://github.com/geemus/fog/tree/master/tests/compute/requests/voxel">tests</a>)</li>
</ul>
<p><span id="more-8009"></span></p>
<h3>Contribution Overhaul</h3>
<p><a href="http://geymus.s3.amazonaws.com/geemus_fog_shirt.jpg"><img class="alignright size-medium" src="http://geymus.s3.amazonaws.com/geemus_fog_shirt.jpg" alt="geemus + fog shirt" /></a></p>
<p>I am always looking for ways to make it easier for people to get involved, so let me know if you have suggestions. First off I made the standing t-shirt offer <a href="https://github.com/geemus/fog/commit/bc236b94c322889c7622da40524d4b727dd64683#L0R114">more explicit</a>, but that didn't have too much impact.</p>
<p>After that I decided I ought to better groom the <a href="https://github.com/geemus/fog/issues">issues</a> so that they would be more accessible.  The clearest thing is that must issues are now labeled as either easy, medium or hard.  Rather than just plucking these values out of thin air I consider each issue and add notes on what needs to be done to accommodate them before adding the label.  So if you would like to help out you can pick a difficulty matching the time you have available and familiarity with the code and feel confident that everything you need to complete the task will be available.  You can also feel free to skip the non-categorized tickets, since I either haven't figured out how to do them or they will require my attention directly (i.e. accepting pull requests).</p>
<h3>Integrations</h3>
<p>In addition to working inside fog I have been working to help others better use it. Both <a href="https://github.com/jnicklas/carrierwave">carrierwave</a> and <a href="https://github.com/thoughtbot/paperclip">paperclip</a> have received patches with fog support. Both of these libraries provide ways to handle files for users in your web apps and by adding fog support they no longer have to worry about supporting numerous different providers and they can focus on their specialties.  We will have more details about these integrations and how you can take advantage of them in future posts.</p>
<h3>On the Road</h3>
<p>I have also been privileged to be accepted to speak at a number of conferences and meetups. I spoke in January at <a href="http://www.meetup.com/rubymeetup/events/15249365/">Silicon Valley Ruby on Rails Group</a> (<a href="http://marakana.com/forums/ruby/ruby_on_rails/247.html">recorded talk video here</a>) and in February at <a href="http://magic-ruby.com/">Magic Ruby</a>. Yesterday I presented at <a href="http://mtnwestrubyconf.org/2011/">MountainWest RubyConf</a>, and next month I'll be at <a href="http://www.rubynation.org/">Ruby Nation</a> April 1-2, and <a href="http://reddirtrubyconf.com/">Red Dirt RubyConf</a> April 21-22. If you are out and about at these conferences come say hello and let me know how you use fog.</p>
<h3>Toward 1.0</h3>
<p>With all these improvements and bug fixes I can't help but feel like we must be nearing 1.0.  It will be great to reach that point but I still have a couple things I want to sort out along the way.</p>
<p>Although DNS and storage provide fairly universal access across providers, compute still has a few rough edges.  One key focus will be smoothing differences between the compute providers.</p>
<p>Another goal is to better sort out testing.  There is a working set of tests now, but it is split between rspec and shindo and there are some discrepancies between style and usage throughout.  I'd like to solidify how these will work, as well as making it easier for contributors to run them without have credentials for everything.</p>
<p>Last, but certainly not least is a stronger focus on documentation.  There is a bit here and a bit there currently and I'd like to consolidate things on <a href="http://fog.io">fog.io</a> and make them easier to explore, as well as reworking the generated in-code documentation to be more accessible.</p>
<p>Over all I see 1.0 outside of that as being more of the same great stuff, from bug fixes to new services as things are released and the needs of users change, and beyond 1.0 will be no different.  It is just a stepping stone for us to acknowledge the great level of support and stability we have already reached.
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2011/fog-0-7-0-0-6-0-and-0-5-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Welcome to Cloud DNS</title>
		<link>http://www.engineyard.com/blog/2011/welcome-to-cloud-dns/</link>
		<comments>http://www.engineyard.com/blog/2011/welcome-to-cloud-dns/#comments</comments>
		<pubDate>Wed, 02 Mar 2011 01:20:49 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[DNS]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=7265</guid>
		<description><![CDATA[<p>The power and flexibility of the cloud are amazing. But sometimes it can be a pain to chase your resources around and keep everything up to date. This is especially true of keeping track of addresses for DNS, but thankfully more and more API driven options are available, allowing you to automate your DNS to keep up with your hardware changes.</p>
<h3>Setup</h3>
<p>First, make sure you have fog installed:</p>
<pre lang="ruby" escaped="true">gem install fog</pre>
<p>For this first example we will use Zerigo (see below for how to use other providers). You can signup for Zerigo DNS <a href="https://www.zerigo.com/signup/dns">here</a>. Gather up your new credentials to initialize a connection to the service:</p>
<pre lang="ruby" escaped="true">require 'rubygems'
require 'fog'

# create a connection to the service
dns = Fog::DNS.new({
  :provider     =&gt; 'Zerigo',
  :zerigo_email =&gt; ZERIGO_EMAIL,
  :zerigo_token =&gt; ZERIGO_TOKEN
}
</pre>
<h3>Getting in the Zone</h3>
<p>The first thing you need to do to prepare for your DNS excursion is create a zone for your domain.  The zone will contain all of the more specific records that you will create later.  You will just need to specify the domain, which should be your url without the 'http' or 'www' parts, and an email address.  Then you can create the zone with your DNS connection:<span id="more-7265"></span></p>
<pre lang="ruby" escaped="true">zone = @dns.zones.create(
  :domain =&gt; 'example.com',
  :email  =&gt; 'admin@example.com'
)</pre>
<p>Now that you have a zone you will need to update your registrar to let them know what DNS servers are responsible for your domain.  You can ask the zone what values to use:</p>
<pre lang="ruby" escaped="true">zone.nameservers</pre>
<h3>Spinning Records</h3>
<p>With your new zone in hand you can add records as needed.  First and foremost you will probably want the 'www' version of your site to point to whatever your ip might be:</p>
<pre lang="ruby" escaped="true">record = @zone.records.create(
  :ip   =&gt; '1.2.3.4',
  :name =&gt; 'example.com',
  :type =&gt; 'A'
)</pre>
<p>Adding other records is similarly easy, for instance if we want 'www.example.com' to go to the same place, we can use a cname record:</p>
<pre lang="ruby" escaped="true">record = @zone.records.create(
  :ip   =&gt; 'example.com',
  :name =&gt; 'www',
  :type =&gt; 'CNAME'
)</pre>
<p>Or, similarly you might want to have your blog elsewhere:</p>
<pre lang="ruby" escaped="true">record = @zone.records.create(
  :ip   =&gt; '4.3.2.1',
  :name =&gt; 'blog.example.com',
  :type =&gt; 'A'
)</pre>
<p>You can add more specifics if you need to, but reasonable defaults make it just that easy.  You can also add any other kind of DNS record you might need for mail or other purposes, you can find a nice overview of record options and types <a href="http://en.wikipedia.org/wiki/Domain_Name_System#DNS_resource_records">on Wikipedia</a>.</p>
<h3>No Zerigo? No Problem</h3>
<p>If you already have an account with another service you can just as easily use this same code with different credentials. fog currently supports <a href="http://aws.amazon.com/route53/">AWS Route 53</a>, <a href="http://bluebox.net">Blue Box</a>, <a href="http://dnsimple.com">DNSimple</a>, <a href="http://www.linode.com">Linode</a>, <a href="http://www.slicehost.com">Slicehost</a> and <a href="http://www.zerigo.com/managed-dns">Zerigo</a>; so you can have your pick.  As an example you can connect to AWS instead of Zerigo:</p>
<pre lang="ruby" escaped="true">dns = Fog::DNS.new({
  :provider               =&gt; 'AWS',
  :aws_access_key_id      =&gt; AWS_ACCESS_KEY_ID,
  :aws_secret_access_key  =&gt; AWS_SECRET_ACCESS_KEY
}</pre>
<h3>Go Forth and Resolve</h3>
<p>You can see an example of reusing code like this in the <a href="https://github.com/geemus/fog/blob/master/examples/dns_tests.rb">examples folder</a>. Using this makes it easier to give yourself shortcuts to your cloud servers and manage how clients and users access them as well. It is great to have this flexibility so that you can modify your cloud infrastructure as needed while keeping everything ship shape. It also provides a nice way to create custom subdomains for users and just generally round out your cloud solution.
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2011/welcome-to-cloud-dns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Faster Websites in 5 Minutes</title>
		<link>http://www.engineyard.com/blog/2011/faster-websites-in-5-minutes/</link>
		<comments>http://www.engineyard.com/blog/2011/faster-websites-in-5-minutes/#comments</comments>
		<pubDate>Fri, 21 Jan 2011 01:55:54 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[cdn]]></category>
		<category><![CDATA[fog]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=6337</guid>
		<description><![CDATA[<p>[caption id="" align="alignright" width="250" caption="Image courtesy of Justice Building Blog"]<a href="http://justicebuilding.blogspot.com/"><img src="http://4.bp.blogspot.com/_CTNBIZIMR0Y/R7ZJgqfxVvI/AAAAAAAAAQU/eDSYIEnn-aM/s400/D737~Speed-Racer-Go-Speed-Posters.jpg" alt="" width="250" height="198" /></a>[/caption]</p>
<p>Faster websites are better. <a href="http://www.websiteoptimization.com/speed/tweak/design-factors/">Better experience</a>, <a href="http://exp-platform.com/Documents/IEEEComputer2007OnlineExperiments.pdf">better sales</a>, <a href="http://www.stevesouders.com/blog/2009/07/27/wikia-fast-pages-retain-users/">you name it</a>. Unfortunately, making a website faster can be tough. Thankfully a content distribution network, or CDN, can give you great performance bang for your buck. A CDN helps speed things up by putting copies of your files closer to your users. It's like the difference between pizza delivery from across the street and pizza delivery from the next town over.</p>
<p>The ease and deliciousness are the good news, but until recently CDN's were only available in the big leagues via 'my business guys will talk to your business guys' deals.  Fortunately for us, Amazon recently updated <a href="http://aws.amazon.com/cloudfront/">CloudFront</a>, their CDN service, to allow us to get these benefits with just a credit card and an API call. So now we'll see how you can spend a few minutes to save your users countless hours of load time.</p>
<p><span id="more-6337"></span></p>
<h2>Preliminaries</h2>
<p>First, make sure you have fog installed:</p>
<pre lang="ruby" escaped="true">gem install fog</pre>
<p>Now you'll need to <a href="https://aws-portal.amazon.com/gp/aws/developer/subscription/index.html?productCode=AmazonCloudFront">sign up for Cloudfront</a>. Gather up the credentials your new credentials to initialize a connection to the service:</p>
<pre lang="ruby" escaped="true">require 'rubygems'
require 'fog'

# create a connection to the service
cdn = Fog::CDN.new({
  :provider               =&gt; 'AWS',
  :aws_access_key_id      =&gt; AWS_ACCESS_KEY_ID,
  :aws_secret_access_key  =&gt; AWS_SECRET_ACCESS_KEY
}</pre>
<h2>Setting Up Your CDN</h2>
<p>Now you'll need to create a 'distribution' which represents a mapping from the CDN to your domain. For the examples we'll pretend we are working on 'http://www.example.com', but you can just switch it to your actual domain. Some <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/CreateDistribution.html">other options</a> are available, but the only other one we need to fill in is OriginProtocolPolicy.  This sets what to do about http vs https. We will use 'match-viewer' which returns the same protocol as the request, but you can also choose 'http-only' which always returns http responses.</p>
<pre lang="ruby" escaped="true"># let the cdn know about your site
data = cdn.post_distribution({
  'CustomOrigin' =&gt; {
    'DNSName'               =&gt; 'www.example.com',
    'OriginProtocolPolicy'  =&gt; 'match-viewer'
  }
})

# parse the response for stuff you'll need later
distribution_id   = data.body['Id']
caller_reference  = data.body['CallerReference']
etag              = data.headers['ETag']
cdn_domain_name   = data.body['DomainName']

# wait for the updates to propogate
Fog.wait_for {
  cdn.get_distribution(distribution_id).body['Status'] == 'Deployed'
}</pre>
<h2>Getting Served</h2>
<p>With the domain name from the distribution in hand you should now be ready to serve content from the edge.  All you need to do is start replacing urls like <code>http://www.example.com/stylesheets/foo.css</code> with <code>#{cdn_domain_name}/stylesheets/foo.css</code>. Just because you can do something doesn't always mean you should though.  Dynamic pages are not really well suited to CDN storage, since CDN content will be the same for every user.  Fortunately some of your most used content is a great fit.  By just switching over your images, javascripts and stylesheets you can have an impact for each and every one of your users.</p>
<p>Congrats, your site is faster! By default the urls aren't very pretty, something like <code>http://d1xdx2sah5udd0.cloudfront.net/stylesheets/foo.css</code>.  Thankfully you can use CNAME config options to utilize something like <code>http://assets.example.com/stylesheets/foo.css</code>, if you are interested in learning more about this let me know in the comments.</p>
<h2>Cleaning Up</h2>
<p>But, just in case you need to update things I'll run through how you can make changes. In my case I just want to clean up after myself, so I'll use the distribution_id and ETag from before to disable the distribution. We need to use the ETag as well because it provides a way to refer to different versions of the same distribution and ensures we are updating the version that we think we are.</p>
<pre lang="ruby" escaped="true">data = cdn.put_distribution_config(
  distribution_id,
  etag,
  {
    'CustomOrigin' =&gt; {
      'DNSName'               =&gt; 'www.example.com',
      'OriginProtocolPolicy'  =&gt; 'match-viewer'
    },
    'CallerReference' =&gt; caller_reference,
    'Enabled' =&gt; 'false'
  }
)

# parse the updated etag
etag = data.headers['ETag']</pre>
<p>Now you just need to wait for the update to happen like before and once its disabled we can delete it:</p>
<pre lang="ruby" escaped="true">Fog.wait_for {
  cdn.get_distribution(distribution_id).body['Status'] == 'Deployed'
}
cdn.delete_distribution(distribution_id, etag)</pre>
<p>Thats it, now go forth and speed up some load times!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2011/faster-websites-in-5-minutes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Happy New Year (and 0.4.0) from fog!</title>
		<link>http://www.engineyard.com/blog/2011/happy-new-year-and-0-4-0-from-fog/</link>
		<comments>http://www.engineyard.com/blog/2011/happy-new-year-and-0-4-0-from-fog/#comments</comments>
		<pubDate>Thu, 06 Jan 2011 18:28:24 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[fog]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=5853</guid>
		<description><![CDATA[<p><a href="http://www.engineyard.com/blog/wp-content/uploads/Picture-31.jpg"><img class="alignright size-medium wp-image-5927" title="Picture 3" src="http://geymus.s3.amazonaws.com/geemus_guitar.jpg" alt="" width="204" height="300" /></a>I'm rocking in 2011 with a bang today by pushing a big "minor" release of <a href="http://github.com/geemus/fog">fog</a>. For those not following along at home, <a href="http://github.com/geemus/fog">fog</a> is a provider agnostic cloud services library for Ruby. If you are a Rubyist using (or considering using) cloud services, look no further, we have you covered with one API for any cloud.</p>
<h3>Contributors, Contributors, Contributors</h3>
<p>One of the most exciting changes has been the reaching the height of over <a href="https://github.com/geemus/fog/contributors">40 contributors</a>, keep up the awesome work everybody! We have fixed tons of bugs, improved docs and added loads of features. So without further ado I'll summarize the new hotness.</p>
<p><span id="more-5853"></span></p>
<h3>New Providers and Services</h3>
<p>First off, several new services have joined the fog family, as well as a few notable additions to the existing services:</p>
<ul>
<li>AWS IAM service for access control of Amazon credentials was added</li>
<li>AWS storage (S3) gained CDN custom origin support and multipart uploads</li>
<li>AWS compute (EC2) gained support for tags and searching resources by filters</li>
<li>New DNS API with support for AWS, Linode, Slicehost and Zerigo</li>
<li>Brightbox contributed a ton of code for their new (still in beta) compute offering</li>
<li>GoGrid compute has just gotten off the ground, with plenty left to work on</li>
</ul>
<h3>Smaller Memory Usage and Safer Credentials</h3>
<p>As the number of services continues to grow I have been working hard to keep things nicely organized.  Toward that goal we have a few additions. Now more than ever fog tries not to load parts of itself (or other gems) unless it needs them, allowing fog to use even less memory and start up faster.</p>
<p>To encourage the best practice of keeping your credentials safely outside your code, it is now easier to setup and use a yaml credential file. You can now use <code>Fog::AWS::Compute.new</code> with no arguments if you have a valid credential file supplied (default is ~/.fog).  To use a different credential file just call <code>Fog.credentials_path = 'path/to/credentials'</code>.</p>
<h3>Focus on Services</h3>
<p>Another big change has been focusing on services more than providers, as mentioned above. New service level initializers simply take a <code>:provider</code>along with the normal credentials, and if you have your credentials file setup all you'll need to specify is the provider:</p>
<pre lang="ruby" escaped="true">  Fog::Compute.new(:provider =&gt; 'AWS')
  Fog::DNS.new(:provider =&gt; 'AWS')
  Fog::Storage.new(:provider =&gt; 'AWS')</pre>
<p>Along with the initializers I have done a great deal of work to smooth out even more differences between the services (especially for storage and DNS). You can see the recommended interoperable way of working with dns and storage in the examples directory. These examples and many tests are now shared between providers to ensure compatibility and interoperability moving forward.</p>
<h3>Community Grows Up</h3>
<p>There were a few non-code changes as well.  We gained a <a href="http://groups.google.com/group/ruby-fog">mailing list</a> where you can see the release notes for all the patch versions, the <a href="irc://irc.freenode.net/ruby-fog">#ruby-fog</a> irc channel, and we're <a href="http://twitter.com/fog">@fog</a> on Twitter if you have questions. We gave out shirts, and added directions on how to score them to the <a href="https://github.com/geemus/fog/blob/master/README.rdoc">README</a> (in case you are curious). And we started on a <a href="http://fog.io">webpage for fog</a>, it still needs a lot of work but you can help by contributing to the gh-pages branch.</p>
<h3>Sponsors</h3>
<p>Since September Engine Yard has given me the awesome opportunity to work full time on fog.  I can't thank them enough for the whirlwind, hectic, but ultimately amazing experience. Engine Yard goes above and beyond paying the bills, helping me get to conferences and covering the awesome stickers and shirts.</p>
<p>Also thank you to Bluebox, Brightbox and GoGrid who all graciously donate resources so that I can run tests. For the other providers I would ask that you please consider getting in touch about donating resources so that I can keep my costs down.</p>
<p>Thanks again to everyone supporting and using fog, looking forward to another great year with my head in the clouds! ;)
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2011/happy-new-year-and-0-4-0-from-fog/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting Hired: fog Edition</title>
		<link>http://www.engineyard.com/blog/2010/getting-hired-fog-edition/</link>
		<comments>http://www.engineyard.com/blog/2010/getting-hired-fog-edition/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 19:34:32 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[fog]]></category>
		<category><![CDATA[Storage]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=5027</guid>
		<description><![CDATA[<p>Having Ruby experience makes you hirable; but how can you stand out? You need to demonstrate your abilities. What better way than using Ruby and "the cloud" to store and serve your resume!</p>
<p>In this blog post you will learn to use <a href="http://github.com/geemus/fog">fog</a> - the cloud computing library - to upload your resume to Amazon's <a href="http://aws.amazon.com/s3/">Simple Storage Service</a> (S3), Rackspace's <a href="http://www.rackspacecloud.com/cloud_hosting_products/files">CloudFiles</a> or Google's <a href="http://code.google.com/apis/storage/">Storage for Developers</a>.</p>
<p>Here's my out of date resume stored on <a href="http://geemus.s3.amazonaws.com/resume.html">S3</a>, <a href="http://c0023559.cdn2.cloudfiles.rackspacecloud.com/resume.html">CloudFiles</a> and <a href="https://geemus.commondatastorage.googleapis.com/resume.html">Google Storage</a>; programmatically stored in the cloud using this tutorial. NOTE: my boss would like me to add that I'm not currently looking for a new gig ;)</p>
<p>Check out those cloud-specific URLs! You could put all three in your job application, add the Ruby source for how you did it, and have your choice of Ruby jobs for being so awesome!</p>
<p>How? The all-clouds-in-one library of choice is <a href="https://github.com/geemus/fog">fog</a>.</p>
<h3>Installing fog</h3>
<p><a href="https://github.com/geemus/fog">fog</a> is distributed as a RubyGem:</p>
<pre escaped="true">gem install fog</pre>
<p>Or add it in your application's Gemfile:</p>
<pre lang="ruby" escaped="true">gem "fog"</pre>
<h3>Using Amazon S3 and fog</h3>
<p>Sign up for an account <a href="http://aws-portal.amazon.com/gp/aws/developer/subscription/index.html?productCode=AmazonS3">here</a> and copy down your secret access key and access key id from <a href="http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key">here</a>. We are about to get into the code samples, so be sure to fill in anything in ALL_CAPS with your own values!</p>
<p>First, create a connection with your new account:</p>
<pre lang="ruby" escaped="true">require 'rubygems'
require 'fog'

# create a connection
connection = Fog::Storage.new(
  :provider                 =&gt; 'AWS',
  :aws_secret_access_key    =&gt; YOUR_SECRET_ACCESS_KEY,
  :aws_access_key_id =&gt; YOUR_SECRET_ACCESS_KEY_ID
)

# First, a place to contain the glorious details
directory = connection.directories.create(
  :key    =&gt; "fog-demo-#{Time.now.to_i}", # globally unique name
  :public =&gt; true
)

# list directories
p connection.directories

# upload that resume
file = directory.files.create(
  :key    =&gt; 'resume.html',
  :body   =&gt; File.open("/path/to/my/resume.html"),
  :public =&gt; true
)
</pre>
<p>If you are anything like me, you will continually tweak your resume. Pushing updates is easy:</p>
<pre lang="ruby" escaped="true">file.body = File.open("/path/to/my/resume.html")
file.save
</pre>
<p>As you can see, cloud storage files in fog are a lot like an ActiveRecord model. Attributes that can be changed and a `#save` method that creates or updates the stored file in the cloud.</p>
<p>But if it took you longer to realize the mistake you might not still have file around, but you've got options.</p>
<pre lang="ruby" escaped="true">directory = connection.directories.get("proclamations1234567890")

# get the resume file
file = directory.files.get('resume.html')
file.body = File.open("/path/to/my/resume.html")
file.save

# also, create(attributes) is just new(attributes).save, so you can also do:
file = directory.files.new(
  :key =&gt; 'resume.html',
  :body =&gt; 'improvements',
  :public =&gt; true
)
file.save
</pre>
<p>Alright, so you (eventually) become satisfied enough to send it off, what is the URL endpoint to your resume?</p>
<pre lang="ruby" escaped="true">puts file.public_url</pre>
<p>Pop that link in an email and you should be ready to cruise job ads and send your resume far and wide (Engine Yard is <a href="http://www.engineyard.com/company/careers/wanted-head-in-the-clouds-engineer">hiring</a>, so check us out!). Now you are set, unless you are interviewing for Google, or Rackspace... Both of these companies have their own cloud storage services, so using Amazon S3 might not be the foot in the door you hoped for.</p>
<p>More clouds? How much extra stuff will you have to do for these services!?! Hardly anything needs to change, you just have to pass slightly different credentials in, but I'm getting ahead of myself.</p>
<h3>Google Storage for Developers</h3>
<p>Sign up <a href="http://gs-signup-redirect.appspot.com/">here</a> and get your credentials <a href="https://sandbox.google.com/storage/m/">here</a>.</p>
<pre lang="ruby" escaped="true">connection = Fog::Storage.new(
  :provider =&gt; 'Google',
  :google_storage_secret_access_key =&gt; YOUR_SECRET_ACCESS_KEY,
  :google_storage_access_key_id =&gt; YOUR_SECRET_ACCESS_KEY_ID
)
</pre>
<h3>Rackspace CloudFiles</h3>
<p>Rackspace has <a href="http://www.rackspacecloud.com/cloud_hosting_products/files">Cloud Files</a> and you can sign up <a href="https://www.rackspacecloud.com/signup">here</a> and get your credentials <a href="https://manage.rackspacecloud.com/APIAccess.do">here</a>.</p>
<pre lang="ruby" escaped="true">connection = Fog::Storage.new(
  :provider =&gt; 'Rackspace',
  :rackspace_username =&gt; RACKSPACE_USERNAME,
  :rackspace_api_key =&gt; RACKSPACE_API_KEY
)
</pre>
<p>Then create, save, destroy as per fog-for-AWS. The `:public =&gt; true` option when creating directories (see above) is important for Rackspace; your folder and files won't be shared to Rackspace's CDN and hence your users without it.  Similarly the `:public =&gt; true` on files is important for AWS and Google or they will be private.</p>
<h3>Local Storage</h3>
<p>While you are working out the kinks you might not want to do everything live though, ditto for while you are running tests, so you have a couple options to try before you buy.  First, you can use a local provider to store things in a directory on your machine.</p>
<pre lang="ruby" escaped="true">connection = Fog::Storage.new(
  :provider =&gt; 'Local',
  :local_root =&gt; '~/fog'
)
</pre>
<h3>Mocking out Cloud Storage</h3>
<p>Of course when you are testing or developing you can always just use the mocks (at least for AWS and Google, Rackspace still needs mocks implemented if you are looking for somewhere to contribute).  They emulate the behavior of the external systems without actually using them.  It is as simple as:</p>
<pre lang="ruby" escaped="true">Fog.mock!
connection = Fog::Storage.new(config_hash)
</pre>
<h3>Cleaning up</h3>
<p>Fog takes care of the rest so you can focus on your cover letter. And with the awesome cover letter and cloud delivered resume you are probably a shoe-in. So all that is left is to cleanup that leftover job hunt residue.</p>
<pre lang="ruby" escaped="true">file.destroy
directory.destroy
</pre>
<h3>Summary</h3>
<p>All done. Try out all the different options and let me know if you have any bugs or issues.  I also wrote up a more <a href="https://gist.github.com/710869">consolidated example as a script</a> that you can use for reference.</p>
<p>Bonus, note the `Fog.mock!` command. In your tests you can easily mock out calls to cloud providers.</p>
<p>Please let me know in the comments if you got a new Ruby job because you hosted your CV on 3 different Cloud Stores without getting your hands dirty.</p>
<p>Have questions or comments?  Hop into <a href="irc://irc.freenode.net/">#ruby-fog</a> on freenode, ping <a href="http://twitter.com/fog">@fog</a> or <a href="http://twitter.com/geemus">@geemus</a>.</p>
<p>And please always remember that I accept high fives and contributions!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2010/getting-hired-fog-edition/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>The Curious Tale of the Humble Micro</title>
		<link>http://www.engineyard.com/blog/2010/the-curious-tale-of-the-humble-micro/</link>
		<comments>http://www.engineyard.com/blog/2010/the-curious-tale-of-the-humble-micro/#comments</comments>
		<pubDate>Tue, 28 Sep 2010 11:45:10 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[EC2]]></category>
		<category><![CDATA[fog]]></category>
		<category><![CDATA[micro instance]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=4737</guid>
		<description><![CDATA[<p>Amazon recently announced micro instances for Elastic Compute Cloud, or EC2. Historically new instance types were larger than existing ones, but this time we got a smaller, more affordable option. It was an exciting announcement for me, as a hobbyist on the look out for servers on the cheap. At 613MB of RAM and two cents per hour, micro instances have roughly a third of the ram, at a quarter of the price of small instances. Small instances are 32 bit, while micro instances (unlike any other types) match the 32 or 64 bit value from their image. Beyond this simple comparison, however, things get a bit pear shaped.</p>
<p>Micro instances have no ephemeral storage, which also means they do not support instance-store images. Instance-store images are stored in snapshots and copied to the ephemeral root device when instances are booted. The alternative is to use volume-store images, which mount the image snapshot on an Elastic Block Store (EBS) volume. Making a choice between instance and volume store involves some trade offs. Instance-store boots slower but costs less. Volume-store boots faster, runs slower at first while data finishes copying and costs more (the price difference comes from EBS transfer/storage costs). Publicly available, supported AMIs do not necessarily provide volume-store versions. A conversion process will allow the transformation of an instance-store image into a volume-store image, but this effectively forks away from the supported version, and it is not clear that it's worth the trouble if your only goal is running micros.</p>
<p>The characteristic of micro instances that probably sticks out the most is the allotted CPU. EC2 describes its machines in terms of Elastic Compute Units, or ECU, each unit equivalent to a 1.0-1.2 GHz 2007 Opteron or 2007 Xeon processor. Instances prior to micro were listed with a number of allotted ECUs, with small providing a reference point at 1 ECU. Micro instances break the trend though, and are listed as providing "Up to 2 EC2 Compute Units (for short periodic bursts)". The <a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/concepts_micro_instances.html">fine print</a> provides some guidelines but no hard numbers. Bursting is everything above some background level much lower than 1 ECU, and is allowed for some percentage of each time period. Unfortunately the specifics are not revealed and bursting out of turn will both be throttled and increase the time before the next burst. To provide context, micro instances are are described as serving tens of requests per minute, with the <a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/concepts_micro_instances.html">fine print</a> containing a number of graphs showing recommended CPU usage patterns.</p>
<p>So, at the end of the day it turns out that micro really is not the new small. They are smaller and have fewer, weirder resources which are allotted in a non-specific way that seems counter to the way many people might use them. Load balancing, proxies, cron or monitoring systems might be workable, but running web or database servers would be pushing your luck. If you need something cheap but consistent, your best bet probably remains small instances (if not a vps or different cloud). If you need affordable, bursty processing, you're probably better served using non-micro spot instances. Based on these considerations, we are not currently rushing to add micro support to Engine Yard AppCloud, where it could easily provide a poor user experience for many customers. However, we will keep these things in mind as they become more tried and as we develop new features.</p>
<p>Anecdotal evidence aside, I welcome you to try them out for yourself:</p>
<pre escaped="true" lang="ruby">
  require 'rubygems'
  require 'fog'

  # NOTE: You should replace ALL_CAPS things, manually or by defining constants
  compute = Fog::AWS::Compute.new(
    :aws_access_key_id =&gt; AWS_ID,
    :aws_secret_access_key =&gt; AWS_KEY
  )

  # bootstrap:
  # uses or creates fog_default keypair from private key to boot server with
  # opens port 22 of the first security specified or 'default' group.
  # an 'EBS boot' ubuntu image list is available: http://alestic.com/
  # waits for the server to be ssh-able, which can take a minute or two
  server = compute.servers.bootstrap(
    :flavor_id =&gt; 't1.micro',
    :image_id =&gt; 'ami-6c06f305',
    :private_key_path =&gt; PRIVATE_KEY_PATH,
    :public_key_path =&gt; PUBLIC_KEY_PATH,
    :username =&gt; 'ubuntu'
  )

  # run some commands over ssh and return results
  server.ssh(ARRAY_OF_COMMANDS_TO_RUN)

  # shutdown the server
  server.destroy
</pre>
<p>Please let us know what you find out!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2010/the-curious-tale-of-the-humble-micro/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The Art of Library</title>
		<link>http://www.engineyard.com/blog/2009/the-art-of-library/</link>
		<comments>http://www.engineyard.com/blog/2009/the-art-of-library/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 18:45:16 +0000</pubDate>
		<dc:creator>geemus (Wesley Beary)</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[S3]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=2521</guid>
		<description><![CDATA[<p>Honk if you love hacking! I know I do, and boy is it ever satisfying to turn a tough problem into a clever solution. But as you tumble down the slippery hacking slopes, picking up loose bits of code, you may find the itch to start writing code for other hackers. Good thought, but realize that implementation is just the tip of the iceberg.</p>
<h2>Library What, Huh?</h2>
<p>What makes libraries so special? They save time and effort by providing code you don't want to write. Skip the nitty gritty of this authentication scheme or that request protocol and get on with the task at hand. There are many ways for a library to capture wily domain knowledge and not all are created equal. After working on some libraries and reading many more, what follows are my personal guidelines for creating lovely encapsulating bits.</p>
<h2>First, Do No Harm</h2>
<p>It should be easier to work with a library than without it. People will grudgingly use libraries that are painful, but will recommend and rave about libraries that feel good. You should start with some idea of what an ideal interaction with the library might feel like. Your first pass at implementation will tend to be rough work, but keep utopia in mind. Subsequent iterations can work to unify reality and awesome.</p>
<p>This happened when I wrote <a href="http://github.com/geemus/shindo">shindo</a>, a test framework that I wrote because I wanted something short and sweet. I have a love/hate relationship with testing. I like the confidence that tests give me, but I'm just not a big fan of the <em>process</em>. Shindo lets me easily understand what's actually happening when tests run. It looks like this:</p>
<pre># Each test is a Ruby block, with success determined by return value
Shindo.tests('examples') do
  test('successful test') { true }
  test('failing test')    { false }
  test('pending test')    # no block provided
end</pre>
<p>My first pass at implementation was basic, but then I started iterating. I wanted the runner to be more interactive than what I was used to. So I added a prompt system that halts the test run when it runs into an error and asks you what you want to do. This led to rapid iterations:</p>
<ol>
<li>I needed backtraces, but I didn't want to raise errors. So I wrote a nice backtrace object and added some code to view its output.</li>
<li>I wanted a better way to sift through files referenced in the backtrace, so I added the ability to choose a line from the backtrace and get an excerpt of the file containing it.</li>
<li>I wanted a better way to debug errors, so I added the choice to launch irb with the same binding as the test block. That's my kind of digging in.</li>
<li>There was no need to run all the tests all the time, so I added tags to help narrow a run down to the relevant ones.</li>
<li>Finally, I added the option to reload files and restart the test run.</li>
</ol>
<p><strong><span id="more-2521"></span></strong></p>
<h2>Keep It Simple</h2>
<p>Libraries should be less complicated than the problems they address. Simple libraries are easier to understand, improve and maintain. Abstractions are a tempting place to start, but they are easier to build on a solid foundation. Start with the simplest thing that could work, staying close to the problem you are trying to solve. For instance, when wrapping public APIs, match the names of attributes and functions to the API documentation. It makes it easier to refer to things and provides documentation from the start.</p>
<p>When I found out I would be joining the <a href="http://www.engineyard.com/products/cloud">Engine Yard Cloud</a> team, it occurred to me that I should have more than a passing knowledge of <a href="http://aws.amazon.com">AWS</a>. I started by reading tons of <a href="http://aws.amazon.com/documentation">docs</a>. Equipped with a rough idea of what was involved, I wanted an easy way to experiment and code AWS. Such was the genesis of <a href="http://github.com/geemus/fog">fog</a>.  AWS interactions can be super complicated, so I started by mapping the docs almost directly to code. Using it looks like this:</p>
<p><a name="low_level"></a></p>
<pre>s3 = Fog::AWS::S3.new(
 :aws_access_key_id =&gt; id,
 :aws_secret_access_key =&gt; key
)

# get a list of buckets
s3.get_service

# create a bucket
s3.put_bucket('bucketname')

# get the contents of that bucket
s3.get_bucket('bucketname')

# delete that bucket
s3.delete_bucket('bucketname')</pre>
<p>I'll be the first to admit that its not the prettiest, but it worked! And when in doubt, the AWS documentation could remind me what in the world some method I wrote a month ago was supposed to do. Recently someone asked if I had generated this code somehow. I wrote it all by hand (unless you count copy/paste as code generation), but for once it was oddly comforting to be mistaken for a robot.</p>
<h2>Stay Focused</h2>
<p>Stick to capturing stuff for one problem at a time. If sub-sections start getting distracting, consider extracting them into their own libraries. Avoid monkey patching; use inheritance or something that is not monkey patching. Premature optimization is the root of all evil, iteration is the trunk of all good. Do not undermine your tree, and do furnish it with leaves of documentation so that it does not wither and die.</p>
<p>While working on shindo, I ended up adding lots of backtrace related code. Since I was not relying on raised errors, I needed some other way to control starting and stopping tracing. At first it was small and self-contained, like this:</p>
<pre>class Annals

  attr_accessor :buffer, :max

  def initialize(max = 20, &amp;block)
    @max = max
    start
  end

  def lines
    @buffer.map do |event|
      "#{event[:file]}:#{event[:line]} #{event[:method]}"
    end
  end

  def start
    @buffer = []
    @size   = 0
    Kernel.set_trace_func(
      lambda { |event, file, line, id, binding, classname|
        if event == 'call'
          unshift(:file =&gt; file, :line =&gt; line, :method =&gt; "in #{id}")
        end
      }
    )
  end

  def stop
    Kernel.set_trace_func(lambda {})
    @buffer.shift # remove Annals#stop from buffer
  end

  def unshift(line)
    @buffer.unshift(line)
    if @size == @max
      @buffer.pop
    else
      @size += 1
    end
  end

end</pre>
<p>But it just kept growing. So I pulled it out into its own project, <a href="http://github.com/geemus/annals">annals</a>. After extraction I could proceed to add other handy backtrace related features, even ones I had no real need for just then. Small libraries like this make great building blocks for newer, crazier stuff.</p>
<h2>Add Value</h2>
<p>Once equipped with more knowledge about the problem than is healthy for any one person, abstraction is a go. Tackle low hanging fruit first. Ruby is, afterall, object-oriented, so consider providing some nice models that encapsulate the nitty gritty bits. Write mocks. No one knows better what mocks should do. Add some command line tools or an interactive mode. Focus on eliminating pain points, increasing usability and generally making the project awesome to work with.</p>
<p>With a good foundation of low level functionality in <a href="http://github.com/geemus/fog">fog</a>, it was time to start adding value. I added easy mocking, because running tests against AWS can be expensive and slow. Then I started building objects around the various entities. Here is how the objects replace the low level calls from earlier:</p>
<pre># this is optional and great for testing
Fog.mock!

# connection
s3 = Fog::AWS::S3.new(
 :aws_access_key_id =&gt; id,
 :aws_secret_access_key =&gt; key
)

# get a list of buckets
s3.buckets.all

# create a bucket
bucket = s3.buckets.create(:name =&gt; 'bucketname')

# get the contents of that bucket
bucket.objects.all

# delete that bucket
bucket.destroy</pre>
<p>The new interface mimics <a href="http://github.com/datamapper/dm-core">DataMapper</a>, an interface myself and many others are already familiar with. I did my best to abstract away the nitty gritty captured in the low level functionality while leaving the ability to get stuff done. I think it is better, but it is still a work in progress. I dedicate a little time every day to filling in the blanks, but libraries have a way of never truly being finished.</p>
<h2>Lather, Rinse, Repeat</h2>
<p>Making libraries that capture a domain and feel good to use is hard. Implement the simplest thing first, but never stop iterating. Be absurdly consistent. Keep fiddling with the look and feel. If something seems painful, it probably is, so fix it. Make your code a joy to use and people will reward you by using it, and submitting patches (hint, hint)!</p>
<p>What do you think makes a good library? How can I improve <a href="http://github.com/geemus">mine</a>? Comment and let me know!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2009/the-art-of-library/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

