<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

    <title>unethical blogger</title>
 
 <link href="http://unethicalblogger.com/" />
 <updated>2013-04-07T23:46:54-07:00</updated>
 <id>http://unethicalblogger.com/</id>
 <author>
   <name>R. Tyler Croy</name>
   <email>tyler@linux.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/UnethicalBlogger" /><feedburner:info uri="unethicalblogger" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Async sockets in Ada</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/rkoWoMhu9xY/async-with-ada.html" />
   <updated>2013-04-07T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2013/04/07/async-with-ada</id>
   <content type="html">&lt;p&gt;Recently I've been experimenting with the concept of a high-performance (high
parallelism, high concurrency, low CPU/memory footprint) TCP server in Ada. Developing on
top of Linux, you cannot help avoid the
&lt;a href="https://en.wikipedia.org/wiki/epoll"&gt;epoll(7)&lt;/a&gt; I/O event notification
system.&lt;/p&gt;

&lt;p&gt;Unlike my previous post &lt;a href="/2013/03/09/dynamic-tasks-in-ada.html"&gt;on dynamic task creation in
Ada&lt;/a&gt;, this post won't have much in the
way of sample code and walk-through. Mostly because I didn't want to spend the
entire post explaining &lt;code&gt;epoll(7)&lt;/code&gt; concepts.&lt;/p&gt;

&lt;p&gt;If you're currently unfamiliar with
epoll, I found &lt;a href="https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/"&gt;this post from
banu.com&lt;/a&gt;
interesting and useful. In general, I think that it is very useful to
understand how both &lt;code&gt;epoll(7)&lt;/code&gt; and its BSD-friendly pal &lt;code&gt;kqueue(2)&lt;/code&gt; work, and
how the two have influenced evented I/O systems that have become popular in the
past few years.&lt;/p&gt;

&lt;p&gt;For my experiment, the primary challenge with using &lt;code&gt;epoll(7)&lt;/code&gt; is wrapping the
C code with Ada, which on its face this isn't terribly difficult. That said,
mapping C arrays and other stupid pointer tricks that C libraries are prone to
using, can make writing an Ada binding much more difficult. I don't
intend to dive too deep into how one can create such a binding since I think
Felix Krause's post on &lt;a href="http://flyx.org/2012/06/13/adabindings1/"&gt;writing thin/thick C bindings in
Ada&lt;/a&gt; is a pretty good introduction on
that subject. Personally I prefer "thicker" bindings for use in Ada, just as I
expect Ruby libraries to abstract away the more fickle aspects of the
underlying C API.&lt;/p&gt;

&lt;p&gt;What I &lt;em&gt;did&lt;/em&gt; want to share in this post was the actual &lt;strong&gt;working&lt;/strong&gt; results of
my tinkering, which can be found &lt;a href="https://github.com/rtyler/ada-playground/tree/master/epollecho"&gt;here, on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The basic flow of the program (found in &lt;code&gt;main.adb&lt;/code&gt;) is similar to the example
found in the &lt;code&gt;epoll(7)&lt;/code&gt; man page, in that it sets up the &lt;code&gt;epollfd&lt;/code&gt;, binds the
listening to it and then waits for &lt;code&gt;Epoll.Wait&lt;/code&gt; to return with an array of
socket descriptors which have activity on them.&lt;/p&gt;

&lt;p&gt;My next step is to combine this &lt;a href="https://github.com/rtyler/ada-playground/blob/master/epollecho/src/epoll.ads"&gt;basic epoll
binding&lt;/a&gt;
with my &lt;a href="/2013/03/09/dynamic-tasks-in-ada.html"&gt;previous task related
code&lt;/a&gt; and create a TCP server which uses
a task pool to perform "work" on the incoming sockets given to it by an
epoll-listener task.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/rkoWoMhu9xY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2013/04/07/async-with-ada.html</feedburner:origLink></entry>
 
 <entry>
   <title>Safe, Dynamic Task Creation in Ada</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/ZIqx-MXQm6k/dynamic-tasks-in-ada.html" />
   <updated>2013-03-09T00:00:00-08:00</updated>
   <id>http://unethicalblogger.com/2013/03/09/dynamic-tasks-in-ada</id>
   <content type="html">&lt;p&gt;A few years ago,
&lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/Ada_(programming_language"&gt;Ada&lt;/a&gt;
become my hobby/tinker programming language of choice, for a &lt;a href="/2010/12/06/ada-surely-you-jest-mr-pythonman.html"&gt;number of
reasons&lt;/a&gt;, concurrency being
one of them. In this post I'd like to walk you through an example of dynamic
task creation in Ada, which uses &lt;code&gt;Ada.Task_Termination&lt;/code&gt; handlers, a new feature
in Ada 2005.&lt;/p&gt;

&lt;p&gt;(If you're familiar with Ada, you can skip this next section)&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; You can find all this code, and more in my
&lt;a href="https://github.com/rtyler/ada-playground"&gt;ada-playground&lt;/a&gt; repository on GitHub&lt;/p&gt;&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Similar to C, Ada supports stack allocated variables as well as heap allocated
variabels, it also defaults to stack allocation. For example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ada"&gt;&lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
    &lt;span class="c1"&gt;-- A stack allocated `Integer` object&lt;/span&gt;
    &lt;span class="no"&gt;Enough_Memory&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;constant&lt;/span&gt; &lt;span class="kt"&gt;Integer&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="mi"&gt;655360&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;begin&lt;/span&gt;
    &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you wanted to allocate that &lt;code&gt;Integer&lt;/code&gt; onto the heap, then you would use the
&lt;code&gt;new&lt;/code&gt; keyword:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ada"&gt;&lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
    &lt;span class="c1"&gt;-- A heap allocated `Integer` pointer&lt;/span&gt;
    &lt;span class="n"&gt;Enough_Memory&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;access&lt;/span&gt; &lt;span class="kt"&gt;Integer&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="kr"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;(&lt;/span&gt;&lt;span class="mi"&gt;655360&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kr"&gt;begin&lt;/span&gt;
    &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I won't dive too much into the minutia of what is going on here, if you're not
familiar with Ada already you can learn more about &lt;a href="http://en.wikibooks.org/wiki/Ada_Programming/Types/access"&gt;access types on the Ada
Programming
Wikibook&lt;/a&gt;. Basically
we're heap allocating a new Integer and using an  &lt;strong&gt;access type&lt;/strong&gt; (aka: typed
pointer) to keep track of it. Keen readers will notice we didn't do anything
with that Integer access type, and we're &lt;em&gt;technically&lt;/em&gt; leaking the memory. To
solve this we use the generic unit &lt;code&gt;Ada.Unchecked_Deallocation&lt;/code&gt;, which gives
you a facility for properly freeing memory (&lt;a href="http://en.wikibooks.org/wiki/Ada_Programming/Types/access#Deleting_objects_from_a_storage_pool"&gt;more details
here&lt;/a&gt;).&lt;/p&gt;

&lt;hr /&gt;

&lt;h3&gt;Tasking Trickiness&lt;/h3&gt;

&lt;p&gt;Concurrency is part of the language in Ada, and is handled through
&lt;a href="http://en.wikibooks.org/wiki/Ada_Programming/Tasking"&gt;tasking&lt;/a&gt;. A basic
example of might be:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ada"&gt;&lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nn"&gt;Ada.Text_IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
    &lt;span class="kd"&gt;task&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;task&lt;/span&gt; &lt;span class="kr"&gt;body&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
    &lt;span class="kr"&gt;begin&lt;/span&gt;
        &lt;span class="kr"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="kr"&gt;loop&lt;/span&gt;
            &lt;span class="n"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text_IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Put_Line&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;Img&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="kr"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;begin&lt;/span&gt;
    &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The way tasks in Ada work means that the &lt;code&gt;Counter&lt;/code&gt; task will be created,
started and then the execution of the &lt;code&gt;Main&lt;/code&gt; program will block until the
&lt;code&gt;Counter&lt;/code&gt; task completes (important detail).&lt;/p&gt;

&lt;p&gt;The trickiness starts to arrive when you talk about dynamically allocating task
objects, and combine that with something like an infinite loop, such as one
might find in a server program, e.g.:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ada"&gt;&lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
&lt;span class="kr"&gt;begin&lt;/span&gt;
    &lt;span class="c1"&gt;-- Socket set up omitted&lt;/span&gt;
    &lt;span class="kr"&gt;loop&lt;/span&gt;
        &lt;span class="kr"&gt;declare&lt;/span&gt;
            &lt;span class="n"&gt;Client_Socket&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Socket_Type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;Request_Handler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Handler_Ptr&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="kr"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kr"&gt;begin&lt;/span&gt;
            &lt;span class="c1"&gt;-- Block until we receive a new inbound connection&lt;/span&gt;
            &lt;span class="n"&gt;Accept_Socket&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Server_Socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Client_Socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Server_Addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;-- Dereference the Handler_Ptr and call `Process` on the Handler&lt;/span&gt;
            &lt;span class="c1"&gt;-- task&lt;/span&gt;
            &lt;span class="n"&gt;Request_Handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;all&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client_Socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="kr"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;(The code above is an abbreviated version of &lt;code&gt;echomultitask_main.adb&lt;/code&gt; which &lt;a href="https://github.com/rtyler/ada-playground/blob/master/echomultitask_main.adb"&gt;can
be found
here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The issue with this code is that we're allocating a new &lt;code&gt;Handler&lt;/code&gt; task for
every in-bound connection, and we have no means of ever cleaning them up
properly. If we were to create an Array of &lt;code&gt;Handler_Ptr&lt;/code&gt;, we still would have
to find some mechanism (which exists) to check the status of each &lt;code&gt;Handler&lt;/code&gt; to
determine if we should clean it up. Problem being, we'd have to loop through
all the active tasks, checking for a "terminated" status, in order to
deallocate them. It'd be much better if a task could tell us when it's
finished, rather than us polling every one.&lt;/p&gt;

&lt;p&gt;Fortunately in Ada 2005, a mechanism was added to make it easier to add
"clean-up" to tasks: &lt;strong&gt;&lt;code&gt;Ada.Task_Termination&lt;/code&gt;&lt;/strong&gt;. The package allows you to set
up a termination handler for the a specific task, which the runtime will call
when that task terminates. &lt;em&gt;Unfortunately&lt;/em&gt; however, the handler procedure that
can be invoked when the task terminates will &lt;strong&gt;not&lt;/strong&gt; be passed a pointer to
the task itself, but rather the &lt;code&gt;Task_Id&lt;/code&gt; (&lt;code&gt;Ada.Task_Identification.Task_Id&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So close&lt;/strong&gt; to being able to properly deallocate these dynamic tasks, but we
need one more component, a protected object with a hash map inside of it:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ada"&gt;&lt;span class="kd"&gt;package&lt;/span&gt; &lt;span class="nc"&gt;Server.Handlers&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;Coordinator&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
        &lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Track&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Ptr&lt;/span&gt; &lt;span class="p"&gt;: &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;Handler_Ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt;
        &lt;span class="n"&gt;Active_Tasks&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Handler_Containers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Coordinator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Server.Handlers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then back in &lt;code&gt;main.adb&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ada"&gt;    &lt;span class="n"&gt;Accept_Socket&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Server_Socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Client_Socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Server_Addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Request_Handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;all&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client_Socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;-- Make sure the we keep track of the Request_Handler in order to properly&lt;/span&gt;
    &lt;span class="c1"&gt;-- deallocate it later&lt;/span&gt;
    &lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Coordinator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Track&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Request_Handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;(The code above is an abbreviated version of &lt;code&gt;echomultitask-worker.ads&lt;/code&gt; which
&lt;a href="https://github.com/rtyler/ada-playground/blob/master/echomultitask-worker.ads"&gt;can be found
here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The singleton protected object &lt;code&gt;Coordinator&lt;/code&gt; not only will give us protected
(aka thread safe) access to the &lt;code&gt;Active_Tasks&lt;/code&gt; map, but also gives us a
protected object to hang our &lt;code&gt;Ada.Task_Termination.Termination_Handler&lt;/code&gt;
protected procedure off of:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ada"&gt;&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kr"&gt;body&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handlers&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kr"&gt;body&lt;/span&gt; &lt;span class="n"&gt;Coordinator&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;

        &lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Last_Wish&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="p"&gt;: &lt;/span&gt;&lt;span class="nv"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Task_Termination&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Cause_Of_Termination&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                             &lt;span class="nv"&gt;T&lt;/span&gt; &lt;span class="p"&gt;: &lt;/span&gt;&lt;span class="nv"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Task_Identification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Task_Id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                             &lt;span class="nv"&gt;X&lt;/span&gt; &lt;span class="p"&gt;: &lt;/span&gt;&lt;span class="nv"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Exception_Occurrence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
        &lt;span class="kr"&gt;begin&lt;/span&gt;
            &lt;span class="c1"&gt;-- Deallocate our task identified by `T`&lt;/span&gt;
            &lt;span class="c1"&gt;-- and make sure we remove it from `Active_Tasks`&lt;/span&gt;
        &lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Last_Wish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;procedure&lt;/span&gt; &lt;span class="nf"&gt;Track&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Ptr&lt;/span&gt; &lt;span class="p"&gt;: &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;Handler_Ptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;is&lt;/span&gt;
            &lt;span class="c1"&gt;-- Dereference our `Handler` task, and fish out its Task_Id&lt;/span&gt;
            &lt;span class="n"&gt;Handler_Id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;Task&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;Idenfitication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;Task&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;all&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;Identity&lt;/span&gt;
        &lt;span class="kr"&gt;begin&lt;/span&gt;
            &lt;span class="c1"&gt;-- Add `Handler_Id` to our `Active_Tasks` map&lt;/span&gt;
            &lt;span class="n"&gt;Active_Tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Handler_Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;-- Set up the Last_Wish procedure to be executed after our task has&lt;/span&gt;
            &lt;span class="c1"&gt;-- terminated&lt;/span&gt;
            &lt;span class="n"&gt;Ada&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;Task&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;Termination&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set_Specific_Handler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Handler_Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Last_Wish&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;Access&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Coordinator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;end&lt;/span&gt; &lt;span class="nf"&gt;Server.Handlers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;(The code above is an abbreviated version of &lt;code&gt;echomultitask-worker.adb&lt;/code&gt; which
&lt;a href="https://github.com/rtyler/ada-playground/blob/master/echomultitask-worker.adb"&gt;can be found here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This approach will allow us to safely create new dynamic tasks to handle the
incoming requests, but will also make sure that the tasks are cleanly
deallocated when they terminate.&lt;/p&gt;

&lt;p&gt;If you're interested in concurrency in Ada, I
highly recommend purchasing &lt;a href="http://www.amazon.com/gp/product/0521866979?ie=UTF8&amp;amp;tag=unethicalblog-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0521866979"&gt;Concurrent and Real-Time Programming in
Ada&lt;/a&gt;
by Alan Burns and Andy Wellings, it's been tremendously helpful for my own
concurrency exploration in Ada.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/ZIqx-MXQm6k" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2013/03/09/dynamic-tasks-in-ada.html</feedburner:origLink></entry>
 
 <entry>
   <title>Tyler goes to Yurp</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/LpNiwwI2AMA/tyler-goes-to-yurp.html" />
   <updated>2012-12-13T00:00:00-08:00</updated>
   <id>http://unethicalblogger.com/2012/12/13/tyler-goes-to-yurp</id>
   <content type="html">&lt;p&gt;As I mentioned in my &lt;a href="/2012/11/18/testing-automation-devroom-fosdem.html"&gt;previous
post&lt;/a&gt; I'll be going to
&lt;a href="http://fosdem.org"&gt;FOSDEM&lt;/a&gt; this year. Unlike last year, I will be spending a
&lt;em&gt;lot&lt;/em&gt; more time in Europe this time around.&lt;/p&gt;

&lt;p&gt;I will be arriving in Frankfurt on the 29th of January and spending a few days
in K&amp;ouml;ln (Cologne). Naturally I will be in Brussels for FOSDEM for a couple
days, but after that, I will be heading to
&lt;a href="https://en.wikipedia.org/wiki/Berlin"&gt;Berlin&lt;/a&gt; for a few weeks.&lt;/p&gt;

&lt;p&gt;I've already spent a good amount of time in Germany, so I won't be on the
"tourist track", having seen most of the sights in Berlin already.&lt;/p&gt;

&lt;p&gt;So I will be working from Berlin, and my weekends and evenings will be open to
as many meetups/hackathons as I can find. Even if you don't want to hang out
(it's okay, I understand), but know of some good events in Berlin that are
worth checking out, please send me an email (tyler@linux.com) and let me know!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;What the hell is Yurp?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Having spent a large amount of my time in the southern US, "Yurp" is how &lt;em&gt;far&lt;/em&gt;
too many southern people pronounce "Europe", including those in my own family.
That's why I'm going to Yurp.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/LpNiwwI2AMA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/12/13/tyler-goes-to-yurp.html</feedburner:origLink></entry>
 
 <entry>
   <title>FOSDEM: Testing and Automation Dev Room CFP</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/IIm5KLy_SsQ/testing-automation-devroom-fosdem.html" />
   <updated>2012-11-18T00:00:00-08:00</updated>
   <id>http://unethicalblogger.com/2012/11/18/testing-automation-devroom-fosdem</id>
   <content type="html">&lt;p&gt;For this next year's FOSDEM, I'm organizing the "Testing and Automation"
developer room. And wouldn't you know it, we've just opened up our &lt;a href="https://gist.github.com/4107243"&gt;Call for
Participation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm quite excited about the dev room, and look forward to reviewing and
selecting the talks.&lt;/p&gt;

&lt;p&gt;Hope to see you there :)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/IIm5KLy_SsQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/11/18/testing-automation-devroom-fosdem.html</feedburner:origLink></entry>
 
 <entry>
   <title>Video: Rebuilding the airplane - Continuous Deployment with Gerrit and Jenkins</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/GhrxcXam09A/video-continuous-deployment-gerrit-jenkins.html" />
   <updated>2012-10-21T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/10/21/video-continuous-deployment-gerrit-jenkins</id>
   <content type="html">&lt;p&gt;I promise this is the last video I'll post for a while. This talk was given at
&lt;a href="http://www.cloudbees.com/jenkins-user-conference-2012-san-francisco.cb"&gt;Jenkins User Conference
2012&lt;/a&gt;
in San Francisco at the end of September.&lt;/p&gt;

&lt;p&gt;This talk can be considered part of the same overarching narrative behind my
&lt;a href="/2012/10/08/selenium-meetup-video.html"&gt;Integrating Selenium after the
fact&lt;/a&gt; presentation. Both talks are
addressing the same continuous deployment/delivery project at Lookout.&lt;/p&gt;

&lt;p&gt;I apologize for some of the clipping of the slides in the presentation, use
your imagination to fill in the space to the left of the screen.&lt;/p&gt;

&lt;hr /&gt;

&lt;center&gt;
&lt;iframe width="640" height="360"
src="https://www.youtube-nocookie.com/embed/BkLNK3V8iOo" frameborder="0"
allowfullscreen&gt;&lt;/iframe&gt;
&lt;/center&gt;


&lt;hr /&gt;

&lt;h3&gt;Slides&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://strongspace.com/rtyler/public/rebuilding-at-10000m.pdf"&gt;PDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://strongspace.com/rtyler/public/rebuilding-at-10000m.notes.pdf"&gt;PDF with notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/GhrxcXam09A" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/10/21/video-continuous-deployment-gerrit-jenkins.html</feedburner:origLink></entry>
 
 <entry>
   <title>Video: Red, green, reprovision. Test Driving Operations</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/Sgg-A7vs55E/video-test-driven-ops.html" />
   <updated>2012-10-20T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/10/20/video-test-driven-ops</id>
   <content type="html">&lt;p&gt;One more presentation video from &lt;a href="http://puppetconf.com"&gt;PuppetConf&lt;/a&gt; a couple
weeks ago.&lt;/p&gt;

&lt;p&gt;To be honest, I'm not terribly pleased with this presentation. It's the first
presentation in a long time where I felt like I was overly-nervous to the point
where it was affecting my ability to present. Watching the video after the fact
though, seems like the presentation went alright.&lt;/p&gt;

&lt;p&gt;(I also did a crap job explaining what
&lt;a href="https://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;BDD&lt;/a&gt;. Shit happens
I suppose).&lt;/p&gt;

&lt;p&gt;I still feel strongly about the subject, and look forward to revising this talk
more in the future to cover "more advanced" topics.&lt;/p&gt;

&lt;hr /&gt;

&lt;center&gt;
&lt;iframe width="640" height="360" src="https://www.youtube-nocookie.com/embed/hHcJ0NUIGSI?list=PLV86BgbREluVFB73Wwqp_tCbw5Z9TMLX1&amp;amp;hl=en_US" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/center&gt;


&lt;hr /&gt;

&lt;h3&gt;Slides&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://strongspace.com/rtyler/public/red-green-reprovision.pdf"&gt;PDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://strongspace.com/rtyler/public/red-green-reprovision.notes.pdf"&gt;PDF with
notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/Sgg-A7vs55E" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/10/20/video-test-driven-ops.html</feedburner:origLink></entry>
 
 <entry>
   <title>Video: We'll Do It Live - Operations Anti-Patterns</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/OrAoF3SlX_k/video-well-do-it-live.html" />
   <updated>2012-10-09T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/10/09/video-well-do-it-live</id>
   <content type="html">&lt;p&gt;Another presentation video, this time from &lt;a href="http://puppetconf.com"&gt;PuppetConf&lt;/a&gt;
a couple weeks ago.&lt;/p&gt;

&lt;p&gt;This presentation was a lot of fun to prepare for a give, since it was nothing
but schadenfreude and beer, two of my favorite things. Most talks at PuppetConf
were 35 minutes, but because he likes me so much
&lt;a href="https://twitter.com/stahnma"&gt;Mike&lt;/a&gt; let me run over my time resulting in a
crazy 45 minute talk.&lt;/p&gt;

&lt;center&gt;
&lt;iframe width="640" height="360"
src="https://www.youtube-nocookie.com/embed/b1yKBUP42G0?rel=0" frameborder="0"
allowfullscreen&gt;&lt;/iframe&gt;
&lt;/center&gt;

&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/OrAoF3SlX_k" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/10/09/video-well-do-it-live.html</feedburner:origLink></entry>
 
 <entry>
   <title>Video: Integrating Selenium After the Fact</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/vqGccVOf2Qg/selenium-meetup-video.html" />
   <updated>2012-10-08T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/10/08/selenium-meetup-video</id>
   <content type="html">&lt;p&gt;A few weeks ago I had the fortune to speak at the &lt;a href="http://www.meetup.com/seleniumsanfrancisco/"&gt;SF Selenium
Meetup&lt;/a&gt; with a talk titled:
"&lt;em&gt;Better Late than Never: Integrating Selenium After The Fact&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;This talk is part of a larger Lookout narrative that I've discussed
before around our epic journey to continuous deployment. Alongside some of the
process changes we've enabled, we've also addressed a huge backlog of missing
browser tests which has helped raise our confidence level before shipping code.&lt;/p&gt;

&lt;p&gt;The talk might be a bit rambly, but I hope you find it useful.&lt;/p&gt;

&lt;center&gt;
&lt;iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/ur1d7fYFAYM?list=UUzUaF3G8L5rfoh9xR6a51kg&amp;amp;hl=en_US" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/center&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href="http://strongspace.com/rtyler/public/integrating-se-after-the-fact.pdf"&gt;Slides
here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/vqGccVOf2Qg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/10/08/selenium-meetup-video.html</feedburner:origLink></entry>
 
 <entry>
   <title>Juggling rice</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/VnxYUceUxLU/juggling-rice.html" />
   <updated>2012-09-02T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/09/02/juggling-rice</id>
   <content type="html">&lt;p&gt;For the past couple weeks I've been learning how to juggle in my spare time
(and a bit at work). The act of juggling itself is surprisingly easy, so I
learned &lt;em&gt;how&lt;/em&gt; to juggle in about 2 hours one afternoon, since then I've been
learning how to juggle &lt;strong&gt;well&lt;/strong&gt;, which is much more difficult.&lt;/p&gt;

&lt;p&gt;Thus far I don't know how to do anything other than the &lt;a href="http://kingscascade.com/3BallCascade.html"&gt;standard 3-ball
cascade&lt;/a&gt;, partly due to "poor
equipment" (partially due to "sucking at juggling").&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/agentdero/7910986168/" title="Juggling
balls: Making Of by agentdero, on Flickr"&gt;&lt;img
src="http://farm9.staticflickr.com/8034/7910986168_e9e3108bf9_m.jpg"
width="240" height="180" alt="Juggling balls: Making Of" align="right"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The juggling balls that I purchased on Amazon turned out to be incredibly
light, which makes them much more difficult to catch properly. After lamenting
this fact on the &lt;code&gt;##juggling&lt;/code&gt; IRC channel (on Freenode) I was linked to
&lt;a href="http://www.abc.net.au/science/surfingscientist/jugglingballs.htm"&gt;this guide&lt;/a&gt;
to making your own juggling balls with rice and balloons.&lt;/p&gt;

&lt;br clear="all"/&gt;


&lt;p&gt;Overall I think my wife and I spent about 30 making 5 balls out of probably 20
balloons, including screw-ups. The end result being the nice rice-filled balls
you see below.&lt;/p&gt;

&lt;center&gt;&lt;a href="http://www.flickr.com/photos/agentdero/7910985416/" title="Finished
juggling balls by agentdero, on Flickr"&gt;&lt;img
src="http://farm9.staticflickr.com/8297/7910985416_12db15fa8b_m.jpg"
width="240" height="180" alt="Finished juggling balls"&gt;&lt;/a&gt;&lt;/center&gt;


&lt;p&gt;I'm looking forward to the eventual disaster that's going to happen when the
cat rips one of these open, but until then, I've got some great, weighty
juggling balls to continue practicing with!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/VnxYUceUxLU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/09/02/juggling-rice.html</feedburner:origLink></entry>
 
 <entry>
   <title>Pairing with the fourth wall</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/6_s6H0KSuuM/pairing-with-the-fourth-wall.html" />
   <updated>2012-08-28T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/08/28/pairing-with-the-fourth-wall</id>
   <content type="html">&lt;p&gt;Some time ago I found myself captivated by watching another developer work. Not
anybody that I work with or know in person, but the infamous
&lt;a href="https://twitter.com/notch"&gt;Notch&lt;/a&gt;. Throught some twist of fate I stumbled
across a live stream of &lt;a href="http://www.twitch.tv/notch/"&gt;his&lt;/a&gt; and spent a
non-trivial amount of time watching boxes and code fly by in Eclipse.&lt;/p&gt;

&lt;p&gt;Inspired, I figured I would try out the same set up on my own. The first major
hurdle to overcome was actually &lt;em&gt;streaming&lt;/em&gt; my desktop to
&lt;a href="http://justin.tv/agentdero"&gt;Justin.tv&lt;/a&gt;. After a full evening of searching, and tinkering
with &lt;code&gt;ffmpeg&lt;/code&gt;, I managed to get &lt;a href="https://gist.github.com/3495063#file_screenstream.sh"&gt;this
script&lt;/a&gt; working well
enough to send audio and video across the internets.&lt;/p&gt;

&lt;p&gt;With the "infrastructure" figured out, I started hosting a couple of sessions
while I worked on projects that I'm passionate about. I found the live coding
concept immediately useful when I managed to get live help from an engineer at
&lt;a href="http://puppetlabs.com"&gt;Puppet Labs&lt;/a&gt; while I dug through the &lt;code&gt;Puppet::AST&lt;/code&gt;
parsing code.&lt;/p&gt;

&lt;p&gt;Taking the experiment further, I even tried helping some folks on IRC with
"live support sessions" which were so fruitful that I posted a couple videos
(&lt;a href="https://www.youtube.com/watch?v=ZaF6tMGI0Ps&amp;amp;feature=plcp"&gt;1&lt;/a&gt;,
&lt;a href="https://www.youtube.com/watch?v=S%C2%B8OHZ74KI&amp;amp;feature=plcp"&gt;2&lt;/a&gt;) from them. In the
office, I can say "hey, come over here and look at this" when others need help,
and the live coding stream allowed me to extend that concept to practically
anybody I wished to help.&lt;/p&gt;

&lt;p&gt;I haven't helped anybody in a few months now, I use my typically viewer-less
sessions to help me focus on a single project. Whenever I turn the stream on,
I'm pair-programming with a companion who may or may not be there (considering
the &lt;code&gt;#codingwithrtyler&lt;/code&gt; channel on Freenode is generally empty, I'm guessing
there's nobody watching), but I focus just as if I had another engineer sitting
next to me.&lt;/p&gt;

&lt;p&gt;It's almost like a weird hybrid of pair programming and &lt;a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging"&gt;rubber duck
debugging&lt;/a&gt; now that I
think about it.&lt;/p&gt;

&lt;p&gt;The projects I work are not nearly as visually pleasing as Minecraft, and I
don't have the geek fame that Notch has but I'm perfectly content to stream &lt;a href="http://justin.tv/agentdero"&gt;my
desktop&lt;/a&gt; to zero viewers as long as it proves
useful for evening and weekend hack-sessions.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/6_s6H0KSuuM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/08/28/pairing-with-the-fourth-wall.html</feedburner:origLink></entry>
 
 <entry>
   <title>I'll be speaking at PuppetConf 2012</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/3PcgehRVjnk/speaking-at-puppetconf.html" />
   <updated>2012-08-09T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/08/09/speaking-at-puppetconf</id>
   <content type="html">&lt;p&gt;Today the organizers of &lt;a href="http://puppetconf.com"&gt;PuppetConf&lt;/a&gt; released an
&lt;a href="http://puppetconf.com/uncategorized/an-almost-complete-list-of-puppetconf-speakers-and-topics/"&gt;"almost complete"
list&lt;/a&gt;
of speakers and talks for this year's PuppetConf in San Francisco, guess who's
on it?&lt;/p&gt;

&lt;p&gt;Through some twist of fate, both of my proposed talks were accepted. Originally
I had submitted two sessions to improve the chances that I would be able to
speak on at least one of the many ideas I had swirling around in my head. I
didn't quite expect to have both talks accepted, but here we are.&lt;/p&gt;

&lt;p&gt;I've included the titles and abstracts for both my talks below, be sure to
&lt;a href="http://puppetconf.com/register/"&gt;register soon&lt;/a&gt; so you can also take one of
Puppet Labs' beta certification exams while you're in town.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Red, green, re-provision: Test-driving Operations&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The developers you work with have a new service they're building, and it is
your job to add the appropriate Puppet modules to provision it. Where do you
start? A base image, Vagrant and some tinkering? Editing files in "/etc/puppet"
on a staging Puppet host? What is the most maintainable work-flow which won't
saddle you with technical debt in the future?&lt;/p&gt;

&lt;p&gt;In this talk, I will take you from the "outside" inward, writing tests along
the way with Cucumber and RSpec. This approach encourages you to think more
about where the lines are drawn between the various services and resources
you're configuring. While the work-flow is a departure from the "traditional
sysadmin" role, the resulting modules can be more easily re-used and
re-factored.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;We'll do it live: Operations Anti-Patterns&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;I have done unspeakable things.&lt;/p&gt;

&lt;p&gt;The best indicator of industry experience in Ops is an engineer with regrets.
An engineer who has designed near-perfect systems but due to outside
constraints has had to cut corners. Let's be honest with ourselves and air some
dirty laundry.&lt;/p&gt;

&lt;p&gt;In this talk, I'll take a jovial romp through some of the most heinous
offenders of what could be considered "Ops Anti-Patterns." I'll share maddening
stories from companies that I have worked at as well as stories from
colleagues, who wish to remain nameless.&lt;/p&gt;

&lt;p&gt;Names may be changed to protect the innocent, or guilty, or whatever.&lt;/p&gt;&lt;/blockquote&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/3PcgehRVjnk" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/08/09/speaking-at-puppetconf.html</feedburner:origLink></entry>
 
 <entry>
   <title>JUC Tokyo 2012 Slides and Recap</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/17odBip7Sgc/juc-tokyo-2012-recap.html" />
   <updated>2012-08-08T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/08/08/juc-tokyo-2012-recap</id>
   <content type="html">&lt;p&gt;Just over a week ago I returned from a trip to Tokyo for the &lt;a href="http://build-shokunin.org/juc2012/"&gt;Jenkins User
Conference 2012 - Tokyo&lt;/a&gt;. I attended the
summer &lt;a href="http://codezine.jp/devsumi/"&gt;Developers Summit&lt;/a&gt; and a Jenkins hackathon
while I was in Tokyo, but JUC 2012 was the main event.&lt;/p&gt;

&lt;p&gt;I can't say enough good things about the Japanese Jenkins community, they are
as friendly (if not more so) as all of the other hackers, users and testers
that I've met throughout the years working with the project. My only regret is
that I had to take so much of &lt;a href="https://github.com/kohsuke"&gt;Kohsuke's&lt;/a&gt; time for
translation or assistance due to the language barrier.&lt;/p&gt;

&lt;p&gt;The talk that I gave at JUC Tokyo was titled "Rebuilding the airplane at
10,000m. Continuous Deployment with Jenkins and Gerrit"&lt;/p&gt;

&lt;p&gt;I've uploaded my materials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/rtyler/juc-tokyo-presentation/raw/master/juc-tokyo.pdf"&gt;Slides without notes (pdf)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://strongspace.com/rtyler/public/juc-tokyo-notes.pdf"&gt;Slides with notes (pdf)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rtyler/juc-tokyo-presentation"&gt;Source "code" for the presentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Unfortunately I don't yet have the video to post, so for now you'll have to
take my word when I say the talk went well.&lt;/p&gt;

&lt;p&gt;I look forward to traveling to Tokyo again next year to enjoy the heat, Soba
and to try more of whatever delicious food &lt;a href="https://twitter.com/cynipe"&gt;Sotoru&lt;/a&gt;
and Takashi try to feed me.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/17odBip7Sgc" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/08/08/juc-tokyo-2012-recap.html</feedburner:origLink></entry>
 
 <entry>
   <title>Recipes from the 4th Cookathon</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/qupOw9QG-IQ/cookathon-recipes.html" />
   <updated>2012-07-07T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/07/07/cookathon-recipes</id>
   <content type="html">&lt;p&gt;This past week I hosted a cookout at my place, and cooked a lot of (in my
opinion) good food. Most of the recipes that I used were from one of my
favorite food blogs: &lt;a href="http://foodwishes.blogspot.com/"&gt;Food Wishes&lt;/a&gt; with the
always charasmatic Chef John (aka Chef Juan).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/agentdero/7512914588/" title="The grill by agentdero, on Flickr"&gt;&lt;img
src="http://farm8.staticflickr.com/7137/7512914588_28e375d9ec_n.jpg"
width="320" height="241" alt="The grill" align="right"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started preparing foods at about noon and continued cooking effectively until
around 8 p.m., with help from some of my guests who pitched in as Sous Chefs
and Grill Keepers throughout the afternoon.&lt;/p&gt;

&lt;br clear="all"/&gt;


&lt;p&gt;In order of appearance the dishes I made were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.flickr.com/photos/agentdero/7503829378/in/photostream"&gt;Home-made Sangria&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://foodwishes.blogspot.com/2012/05/almost-cinco-de-mayo-salsa-cruda.html"&gt;Home-made Salsa Cruda&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  &lt;a href="http://www.flickr.com/photos/agentdero/7504081620/" title="Salsa cruda
  ready for a break in the fridge #cookathon by agentdero, on Flickr"&gt;&lt;img
  src="http://farm9.staticflickr.com/8005/7504081620_4728a60a68_m.jpg"
  width="240" height="180" alt="Salsa cruda ready for a break in the fridge
  #cookathon" align="right"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  This was probably the most time-consuming dish since I diced almost a kilo
  of grape tomatoes in order to make it. It was &lt;em&gt;very&lt;/em&gt; tasty on tortilla
  chips though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://foodwishes.blogspot.com/2012/06/balsamic-strawberry-goat-cheese.html"&gt;Balsamic Strawberry Goat Cheese Bruschetta&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  To me, this was the star of the show. I don't have any pictures of it
  though! If you click through to the link from the Food Wishes blog, you'll
  see some photos, mine looked pretty much exactly like Chef John's, and were
  probably just as tasty.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://foodwishes.blogspot.com/2012/05/turkey-shish-kaburgers-seriously-not.html"&gt;Turkey Shish Kaburgers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  Pictured above on the grill, these turkey burgers are exceptionally
  flavorful, and surprisingly light. Whereas beef burgers typically leave me
  feeling a little bloated and greasy, these were filling in a way that allowed
  us to continue feasting on various other meats and veggies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dave's Roasted Potato Salad&lt;/p&gt;

&lt;p&gt;  Not a recipe from Chef John, one from my good friend
&lt;a href="https://twitter.com/stuffonfire"&gt;Dave&lt;/a&gt;. This simple recipe is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;potatoes (small red or Dutch creamer, baby Yukon Gold)&lt;/li&gt;
&lt;li&gt;green onions&lt;/li&gt;
&lt;li&gt;Some mayonaise and mustard&lt;/li&gt;
&lt;li&gt;olive oil, sea salt&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;  Cube the potatoes, toss with olive oil and salt, roast at 450 until tasty.
  Let it cool, toss with mayo and mustard and finely chopped green onions. Serve
  warm!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.flickr.com/photos/agentdero/7505596386/in/photostream"&gt;A fire&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  &lt;a href="http://www.flickr.com/photos/agentdero/7505596386/" title="FIRE
  #cookathon by agentdero, on Flickr"&gt;&lt;img
  src="http://farm8.staticflickr.com/7254/7505596386_d2b0bf8d60_m.jpg"
  width="240" height="180" alt="FIRE #cookathon" align="right"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  Not really a dish, but no cookout in our backyard is complete without a
  fire, typically accompanied by Smores.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;br clear="all"/&gt;



&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/qupOw9QG-IQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/07/07/cookathon-recipes.html</feedburner:origLink></entry>
 
 <entry>
   <title>FW: FW: FW: FW: The Gays are Invading!</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/Ci1Dz_t6M-g/fw-fw-fw-fw-the-gays.html" />
   <updated>2012-06-26T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/06/26/fw-fw-fw-fw-the-gays</id>
   <content type="html">&lt;p&gt;I received a forwarded email which was passed around members of my extended
hillbilly family.&lt;/p&gt;

&lt;p&gt;Just in case you weren't sure whether or not the US was filled with
&lt;strong&gt;unadulterated fucking idiots&lt;/strong&gt;, behold this political action email.&lt;/p&gt;

&lt;p&gt;All links from the email are "REDACTED" because these dicknozzles can go fuck
themselves.&lt;/p&gt;

&lt;hr /&gt;

&lt;blockquote&gt;&lt;p&gt;Dear Pro-family American,&lt;/p&gt;

&lt;p&gt;The Radical Homosexuals infiltrating the United States Congress have a plan:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Indoctrinate&lt;/em&gt; an entire generation of American children with
pro-homosexual propaganda and &lt;em&gt;eliminate&lt;/em&gt; traditional values from American
society.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Their ultimate dream is to create a new America based on sexual
promiscuity in which the values you and I cherish are long forgotten&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I hate to admit it, but if they pass the deceptively named "Student
Non-Discrimination Act," (H.R. 998 &amp;amp; S. 555) that's exactly what theyll do.&lt;/p&gt;

&lt;p&gt;Better named the "Homosexual Classrooms Act," its chief advocate in
Congress is Rep. Jared Polis, himself an open homosexual and radical
activist.&lt;/p&gt;

&lt;p&gt;And it's dangerously close to becoming the law of the land.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;H.R. 998 already has 157 co-sponsors in the House!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And S. 555 already has 37 co-sponsors in the Senate!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's why I need you to act quickly -- right away -- to protect our
nation's youth.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I have prepared the official "Protect Our Children's Innocence" Petition
to Congress for you to sign&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Please click here REDACTED to
sign it right away so I can rush it to the Capitol with thousands
more.&lt;/p&gt;

&lt;p&gt;You and I must defeat this disastrous legislation.&lt;/p&gt;

&lt;p&gt;You see, the Homosexual Classrooms Act contains a laundry list of
anti-family provisions that will:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;* &lt;/em&gt;Require schools to teach appalling homosexual acts&lt;/em&gt; so "homosexual
students" don't feel "singled out" during already explicit sex-ed classes;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;* &lt;/em&gt;Spin impressionable students&lt;/em&gt; in a whirlwind of sexual confusion and
misinformation, even peer pressure to "experiment" with the homosexual
"lifestyle;"&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;&lt;em&gt; &lt;/em&gt;Exempt homosexual students from punishment&lt;/em&gt; for propositioning,
harassing, or even &lt;/em&gt;sexually assaulting their classmates*, as part of their
specially-protected right to "freedom of self-expression;"&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;&lt;em&gt; &lt;/em&gt;Force private and even religious schools&lt;/em&gt; to teach a pro-homosexual
curriculum and &lt;/em&gt;purge any reference to religion* if a student claims it
creates a "hostile learning environment" for homosexual students.&lt;/p&gt;

&lt;p&gt;And that's just the beginning of the Homosexual Lobbys radical agenda.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In fact, it will set them up to ram through their entire perverted vision
for a homosexual America&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My friend, I'm sure I dont have to tell you this is not a fight we can
afford to lose.&lt;/p&gt;

&lt;p&gt;That's why Public Advocate is leading the fight against this immoral
legislation.&lt;/p&gt;

&lt;p&gt;But I need your help to do it.&lt;/p&gt;

&lt;p&gt;You see, it's becoming harder and harder to send my message to unaware
pro-Family advocates.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Radical Homosexual Lobby is working day and night to censor Public
Advocate's warning about the Homosexual Classrooms Act.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's why, along with your signed petition, I need you to seriously &lt;em&gt;consider
chipping in a special
contribution&lt;/em&gt; REDACTED to
Public Advocate.&lt;/p&gt;

&lt;p&gt;A contribution of just $20 will enable me to email 1,000 potential new
supporters.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a battle for the survival of American values and the fact is,
there's no time to waste&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The Homosexual Classrooms Act will turn America's schools into
indoctrination centers and its classrooms into social laboratories -- and
they're pulling out all the stops to pass it.&lt;/p&gt;

&lt;p&gt;You see, they've disguised the bills wicked purpose behind an innocent
name: "The Student Non-Discrimination Act."&lt;/p&gt;

&lt;p&gt;The Homosexual Lobby knows that if the public knew the truth about their
radical agenda, they'll have no hope of success.&lt;/p&gt;

&lt;p&gt;And their dangerously close to ramming their perversity into law.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;H.R. 998 already has 157 co-sponsors in the House!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And S. 555 already has 37 co-sponsors in the Senate!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You and I need to take action right now to stop the growing momentum of
this disastrous legislation.&lt;/p&gt;

&lt;p&gt;I've developed a massive program to launch the &lt;em&gt;second&lt;/em&gt; they try to push
this bill through -- mail, email, phones, and even radio and TV ads.&lt;/p&gt;

&lt;p&gt;But that's only possible with your support...&lt;/p&gt;

&lt;p&gt;None of these things are cheap.  In fact, running a program of the size
necessary to defeat this bill can get quite expensive especially with
increases in postage and printing costs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That's why I need your generous contribution&lt;/em&gt;.  In addition to your signed
"Protect Our Children's Innocence" Petition, will you &lt;em&gt;contribute $250,
$100, $50 or even just
$35&lt;/em&gt; REDACTED right
away.&lt;/p&gt;

&lt;p&gt;$250 will allow me to email more than 10,000 potential new supporters.
$100 or even $50 would mean 5,000 or 2,500 new chances to alert more
Americans to the threat of the Homosexual Classrooms Act.&lt;/p&gt;

&lt;p&gt;Every dollar counts in this fight.  *Even if you can only chip in $10 or $20
it will mean 500 or 1,000 new emails.&lt;/p&gt;

&lt;p&gt;This agenda is nothing new.&lt;/p&gt;

&lt;p&gt;In fact, other countries like Britain are already experimenting with this
kind of legislation, such as mandating public schools inject pro-homosexual
content into every aspect of education.&lt;/p&gt;

&lt;p&gt;Word problems in math classes are now to include homosexual characters.
History classes will document the "civil rights" struggle against the
"oppressive" pro-family establishment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And it's even started to infiltrate our state governments&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In California, lawmakers want to "require schools to portray lesbians,
homosexuals, transsexuals ... as positive role models to children in all
public schools."&lt;/p&gt;

&lt;p&gt;Sexual deviants being held up as models of virtue?&lt;/p&gt;

&lt;p&gt;If that makes you as sick as it makes me, you simply must join me in this
battle for America's children.&lt;/p&gt;

&lt;p&gt;Please sign the "Protect Our Children's Innocence" Petition to Congress and
then send a &lt;em&gt;generous contribution of at least
$20&lt;/em&gt; REDACTED right away.
&lt;em&gt;Your action will make all the difference&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And if all that wasn't enough to convince you that action must be taken
immediately, there's more.&lt;/p&gt;

&lt;p&gt;Many say that there will always be private schools and traditional
homeschool families to teach traditional values to the next generation.&lt;/p&gt;

&lt;p&gt;But the truth is, * this radical agenda is NOT restricted to public schools*
.&lt;/p&gt;

&lt;p&gt;Kevin Jennings, Obama's "Safe Schools Czar," has clearly stated that "every
school, public, private or parochial has an obligation" to teach a
pro-homosexual curriculum.&lt;/p&gt;

&lt;p&gt;In fact, Jennings denounced school choice programs as "very dangerous"
because they make it much harder to impose the Homosexual Agenda on our
kids.&lt;/p&gt;

&lt;p&gt;"Lord forbid a Baptist or Mormon school," he added.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Jennings' ultimate goal is for all curriculum in "kindergarten, and first
grade, and second grade  every grade" be infused with a pro-homosexual
slant&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Traditional values will be squashed and demonized as old fashioned or out
of date, or even as bigotry.&lt;/p&gt;

&lt;p&gt;You and I cannot let them succeed.&lt;/p&gt;

&lt;p&gt;Please &lt;em&gt;sign the "Protect Our Children's Innocence"
Petition&lt;/em&gt; REDACTED to
Congress I've prepared for you right away.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And along with your petition, would you please send a generous
contribution of $250, $100, $50 or even just
$35&lt;/em&gt;  REDACTED
.&lt;/p&gt;

&lt;p&gt;The Homosexual Lobby has done their worst to censor my message about the
Homosexual Classrooms Act -- and it's absolutely critical that I send more
emails.&lt;/p&gt;

&lt;p&gt;If you contribute as little as $20, I will be able to email 1,000 new
people, maybe even more!&lt;/p&gt;

&lt;p&gt;You see, every dollar counts in this fight so even if you can only &lt;em&gt;chip in
$10 or $20&lt;/em&gt; REDACTED
it will make a significant difference.&lt;/p&gt;

&lt;p&gt;Thank you so much for all you have done.&lt;/p&gt;

&lt;p&gt;Sincerely,&lt;/p&gt;

&lt;p&gt;Eugene Delgaudio
President,
Public Advocate of the U.S.&lt;/p&gt;

&lt;p&gt;P.S. Radical Homosexuals in Congress have a plan to indoctrinate our
children in schools -- both public and private.&lt;/p&gt;

&lt;p&gt;But Public Advocate is taking a stand.  Will you join me?&lt;/p&gt;

&lt;p&gt;Please sign the &lt;em&gt;"Protect Our Children's Innocence"
Petition&lt;/em&gt; REDACTED to
Congress I've enclosed.&lt;/p&gt;

&lt;p&gt;And please, along with your petition, would you please &lt;em&gt;send a generous
contribution&lt;/em&gt; REDACTED of
$250, $100, $50 or even just $35 right away?&lt;/p&gt;

&lt;p&gt;Every $20 will allow me to contact up to a 1,000 potential new pro-Family
supporters -- or more!&lt;/p&gt;

&lt;hr /&gt;

&lt;ul&gt;
&lt;li&gt;Because Public Advocate of the U.S. lobbies against the
Homosexual Lobby, contributions are not tax deductible for IRS purposes.
This email was not produced or e-mailed at taxpayer expense.&lt;/li&gt;
&lt;li&gt;This email is never sent unsolicited. It was sent because of your online
request to receive ongoing news &amp;amp; offers. We respect and value your time
and privacy. We will be happy to remove your address immediately.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;p&gt;Damned gays and their agenda. Derka derka derrrr.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/Ci1Dz_t6M-g" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/06/26/fw-fw-fw-fw-the-gays.html</feedburner:origLink></entry>
 
 <entry>
   <title>Outside-in for Ops, with code!</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/M2-2RV7EYpc/outside-in-to-ops-with-code.html" />
   <updated>2012-06-19T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/06/19/outside-in-to-ops-with-code</id>
   <content type="html">&lt;p&gt;Last week &lt;a href="/2012/06/10/outside-in-to-ops.html"&gt;I discussed&lt;/a&gt; some ideas about
how to apply some
&lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;BDD&lt;/a&gt; concepts to
operations, primarily the "outside-in" approach.&lt;/p&gt;

&lt;p&gt;Over the course of the past couple days, I've been experimenting with some
ideas with my "&lt;a href="https://github.com/rtyler/pentagram"&gt;PentaGram&lt;/a&gt;" project, and I
think I've made enough progress to write a follow-up blog post.&lt;/p&gt;

&lt;p&gt;It's worth mentioning now that &lt;a href="https://github.com/rtyler/pentagram/commits/"&gt;the
commits&lt;/a&gt; to the repository have a
lot of commentary in the commit messages and are meant to help guide you along
step-by-step.&lt;/p&gt;

&lt;p&gt;I do recommend opening the linked commit messages in a separate window and
check them out as you follow along at home.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In order to best emulate a true outside-in workflow, I started with &lt;a href="https://github.com/rtyler/pentagram/commit/c307db4cfb3b9aec83b401ea14b6dd3f3f783ca2"&gt;this
commit&lt;/a&gt;
which really just added the &lt;code&gt;apphost.feature&lt;/code&gt; file mentioned in the previous
post:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Feature: Serve the PentaGram web application
  In order to serve up PentaGram (and satanic phots)
  to millions of devil worshippers

  As an operations engineer

  App hosts should be configured to run the PentaGram
  web application
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you might expect, this by itself is pretty useless so I wrote out the
first scenario and &lt;a href="https://github.com/rtyler/pentagram/commit/940541c01d84e9f042d0c2303bc9d175bac89c7e"&gt;committed that
too.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I should mention now that between just about every commit, and at every step of
the way I was both running Cucumber and RSpec.&lt;/p&gt;

&lt;p&gt;In order to realistically test the Puppet code underlying the entirety of the
&lt;code&gt;apphost.feature&lt;/code&gt;, I needed to spin machines up and down rapidly, so I
integrated another one of my projects:
&lt;a href="/2012/05/21/introducing-blimpy.html"&gt;Blimpy&lt;/a&gt;. Since this was very
experimental, the majority of my first few hours of work on PentaGram was
consumed making the first couple steps in the scenario work:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: Provision a fresh app host
  Given an empty host
  And the host is to become a PentaGram app host
  When I provision the host
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="https://github.com/rtyler/pentagram/commit/2a323e55345c4b117c318c86242f84787d6a4cb1"&gt;This
commit&lt;/a&gt;
concluded the work on just spinning machines up and down, and marked the
turning point. After this commit I could dig &lt;em&gt;deeper&lt;/em&gt; into actually writing
&lt;a href="http://rspec-puppet.com"&gt;rspec-puppet&lt;/a&gt; tests and &lt;em&gt;real&lt;/em&gt; Puppet code.&lt;/p&gt;

&lt;p&gt;At this point I was ready to start driving the code necessary make the "When I
provision the host" step run correctly. This required me to do a couple things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define a "pentagram-web" module&lt;/li&gt;
&lt;li&gt;Set up the whole module structure inside of the pentagram repo&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Unfortunately as you can see
&lt;a href="https://github.com/rtyler/pentagram/commit/47386fdd8270294cbcdff609f07663db77532374"&gt;here&lt;/a&gt;
getting rspec-puppet up and running properly can be a little bit of work. I
found out as I started to look at pulling in third party modules to manage
things such as Apache, that I needed to create symlinks for them inside my
"pentagram-web" module in order for rspec-puppet to find them properly.&lt;/p&gt;

&lt;p&gt;With the dependencies properly being loaded, I could pull in the Ruby, Apache
and Passenger modules with these commits:
&lt;a href="https://github.com/rtyler/pentagram/commit/47386fdd8270294cbcdff609f07663db77532374"&gt;apache&lt;/a&gt;,
&lt;a href="https://github.com/rtyler/pentagram/commit/a2f35833adb91dc2bf5181d0b507fd2b126cf779"&gt;ruby&lt;/a&gt;,
&lt;a href="https://github.com/rtyler/pentagram/commit/5f02821ee8054606dd5b8241e54a956af392c3d1"&gt;passenger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With these dependencies being pulled into my "pentagram-web" module, I felt
ready to step back &lt;strong&gt;out&lt;/strong&gt; into Cucumber land.&lt;/p&gt;

&lt;p&gt;What I found out when I ran the Cucumber scenario again, and actually
provisioned the machine, was that the Passenger module required some more
dependencies to be installed! Sure, I could have found this out by actually
reading the full documentation on the Passenger module, but who has time for
that these days? I addressed this in &lt;a href="https://github.com/rtyler/pentagram/commit/5367271c145d4e495b264efb06f3c1a7ecf547cb"&gt;this
commit&lt;/a&gt;,
which was a good reminder that it doesn't matter how good your RSpec is,
there's nothing quite like &lt;em&gt;actually running your code&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Once everything was provisioning "mostly" properly, I was left to jump back
"out" to Cucumber and implement the last two step definitions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Then it should be running a web server
And it should be responding to web requests
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I thought about how best to implement this, and decided on the most simple
solution (in my opinion): ssh into the box and look! The reason I went for this
approach was to keep things simple, I could have made web requests to the
machine, but I wanted to focus on the bare minimum needed to pass the test. For
the first step I executed "&lt;code&gt;pgrep httpd&lt;/code&gt;" and made sure it returned a zero exit
code. For the second step, I invoked &lt;code&gt;curl&lt;/code&gt; against &lt;code&gt;localhost&lt;/code&gt; and made sure
that it could connect properly.&lt;/p&gt;

&lt;p&gt;What I found out when I implemented these two steps was that...I actually was
&lt;strong&gt;failing my Cucumber!&lt;/strong&gt; In another great example of there being no substitute
for running the code, I discovered an unspecified dependency in the Puppet
resource graph between the Passenger module and Apache, which was fixed &lt;a href="https://github.com/rtyler/pentagram/commit/5f07a8dfb7662604184994e7422bdcd209c36ea5"&gt;in
this
commit&lt;/a&gt;.
Even though Puppet was provisioning the host correctly, it was failing to
correctly start Apache, and thus failed the scenario!&lt;/p&gt;

&lt;h3&gt;Lessons Learned&lt;/h3&gt;

&lt;p&gt;The most important lesson I learned in this exercise was that you &lt;em&gt;must&lt;/em&gt;
execute your Puppet against a real machine before going to production.
Correctly parsing Puppet, passing
&lt;a href="https://github.com/rodjek/puppet-lint"&gt;puppet-lint&lt;/a&gt; and
&lt;a href="http://rspec-puppet.com"&gt;rspec-puppet&lt;/a&gt; checks is &lt;strong&gt;not&lt;/strong&gt; enough, it must
execute on a machine or else you're really just guessing that it will work in
production.&lt;/p&gt;

&lt;p&gt;A couple weeks ago when I wrote &lt;a href="/2012/06/02/grokking-code-with-puppet.html"&gt;about Puppetizing
OpenGrok&lt;/a&gt; I mentioned using "Tinker
Driven Development." At the time I really didn't know anything about OpenGrok
or how I would manage it with Puppet. I am more convinced now that if I had
taken an "outside-in" appraoch with the
&lt;a href="https://github.com/rtyler/puppet-opengrok"&gt;puppet-opengrok&lt;/a&gt; module, I would
have been able to actually use Behavior/Test Driven Development. Even though I
really didn't know anything about how OpenGrok worked, I knew what behavior I
wanted from the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provisioning isn't the end.&lt;/strong&gt; In my previous post, I talked about "Operations as
a stake-holder" which for this level of "outside-in" I think is fine, but in
the end, Operations is a part of a greater organization. Even though the
code implemented thus far provisons an app host which has &lt;em&gt;effectively&lt;/em&gt;
everything it needs to run PentaGram, it's not actually &lt;em&gt;running&lt;/em&gt; PentaGram.
From the "business perspective" I still haven't done anything! There's no
PentaGram app running, there's no deployment happening, we're still not
satisfying our users' need to post daemonic photos! I'm sure this can be
fleshed out in additional scenarios that could be addressed after I met the
needs of the Operations group.&lt;/p&gt;

&lt;p&gt;It's clearer to me now where outside-in for Operations fits in the overall
scheme of things. I can very easily imagine sitting down with an Operations
Manager and discussing what needs to be done to "make PentaGram production
ready" and in doing so, writing out the features and scenarios mentioned in the
&lt;a href="/2012/06/10/outside-in-to-ops.html"&gt;previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's still some tooling work that I think needs to be done to make this
easier, but I'm optimistic about the future of behavior-driven operations!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/M2-2RV7EYpc" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/06/19/outside-in-to-ops-with-code.html</feedburner:origLink></entry>
 
 <entry>
   <title>SSH as a Hidden Service with Tor</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/aGMnqGS8GSA/ssh-as-a-hidden-service.html" />
   <updated>2012-06-13T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/06/13/ssh-as-a-hidden-service</id>
   <content type="html">&lt;p&gt;For quite some time I've been using &lt;a href="https://www.torproject.org"&gt;Tor&lt;/a&gt; for a
number of things, but my most recent use revolves around a lesser-known feature
Tor provides: &lt;a href="https://www.torproject.org/docs/hidden-services.html.en"&gt;Hidden Services&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With fewer and fewer IPv4 addresses running around, especially among
residential consumer lines, it has become increasingly difficult to "play a
part" in the internet without gnarly port forwarding hacks combined with
dynamic DNS.&lt;/p&gt;

&lt;p&gt;Hidden Services offer a way to bypass a lot of those hacks altogether, but it
comes at a cost of some latency. Basically you need to connect both ends of the
connection, the SSH server and SSH client, to the Tor network and let it handle
discovery and routing for you.&lt;/p&gt;

&lt;center&gt;&lt;img alt="Fancy diagram!"
src="http://agentdero.cachefly.net/unethicalblogger.com/images/tor-hidden-service.png"/&gt;&lt;/center&gt;


&lt;ol&gt;
&lt;li&gt;Set up a Hidden Service &lt;a href="https://www.torproject.org/docs/tor-hidden-service"&gt;by following these instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Store your &lt;code&gt;.onion&lt;/code&gt; hostname on your "client" computer&lt;/li&gt;
&lt;li&gt;Run Tor on your "client" computer&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following entry to you &lt;code&gt;~/.ssh/config&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; Host *.onion
   ProxyCommand /usr/bin/nc -xlocalhost:9050 -X5 %h %p
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run SSH to your &lt;code&gt;.onion&lt;/code&gt; hostname: &lt;code&gt;ssh username@shallots.onion&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Profit? Probably not, but who cares, you can now access all of your machines on
&lt;em&gt;any&lt;/em&gt; network from &lt;em&gt;anywhere&lt;/em&gt; around the globe!&lt;/li&gt;
&lt;/ol&gt;


&lt;hr /&gt;

&lt;p&gt;It's worth noting again that latency will be sticking point, so I probably
wouldn't use this for developing in a remote &lt;code&gt;tmux&lt;/code&gt; session, but I would use it
for using SFTP to transfer files to and from the server (for example).&lt;/p&gt;

&lt;p&gt;Addtionally, &lt;a href="https://www.torproject.org/docs/tor-hidden-service"&gt;with the instructions
above&lt;/a&gt; it's trivial to set
up hidden web servers, hidden jabber servers, etc.&lt;/p&gt;

&lt;p&gt;Use responsibly!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/aGMnqGS8GSA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/06/13/ssh-as-a-hidden-service.html</feedburner:origLink></entry>
 
 <entry>
   <title>Outside-in for Operations</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/Xb8QSbPN0rA/outside-in-to-ops.html" />
   <updated>2012-06-10T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/06/10/outside-in-to-ops</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I've posted the &lt;a href="/2012/06/19/outside-in-to-ops-with-code.html"&gt;update to this post
here&lt;/a&gt; which contains some code
and more fully fleshed out ideas&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I have been thinking a lot about "outside-in" developement for operations as of
late, primarily focusing on how &lt;a href="http://cukes.info"&gt;Cucumber&lt;/a&gt; might fit into
the equation.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.nistu.de/2012/06/09/cucumber-puppet-end-of-life/"&gt;cucumber-puppet&lt;/a&gt;
reached its "end-of-life" recently as the developer can no longer provide the
tender love and code (TLC) that the project requires. I don't particularly like
the way cucumber-puppet works but at the same time, I've been faced with more
and more questions about how to bridge into, or out of,
&lt;a href="http://rspec-puppet.com/"&gt;rspec-puppet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a development tool rspec-puppet is quite handy, but at the end of the day,
Puppet manifests should be run in an actual Puppet environment on real or
virtualized hardware before they get shipped off to the production site.&lt;/p&gt;

&lt;p&gt;What does that look like?&lt;/p&gt;

&lt;p&gt;Before you answer that, I think it is important to answer "who are the
stake-holders?" for the work that operations is doing?&lt;/p&gt;

&lt;h3&gt;Developers as Stake Holders&lt;/h3&gt;

&lt;p&gt;Let's say I'm developing an application called "PentaGram", this is a simple
Rails application that will help Satan worshippers upload evil photos and share
them with their fellow demonic friends.&lt;/p&gt;

&lt;p&gt;To host PentaGram, I'm going to need a web server, an Oracle database (this
application is evil, after all) and memcached. I think for now I'll just break
up my Cucumber &lt;code&gt;.feature&lt;/code&gt; files into machine types (web, db, cache).&lt;/p&gt;

&lt;p&gt;For this post, i'll focus on &lt;code&gt;featurees/apphost.feature&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Feature: Serve the PentaGram web application
  In order to serve up the PentaGram to millions of devil worshippers
  As a developer
  Web hosts should be configured to run the application
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I think this makes sense as an 'introduction' to the feature, I need web hosts
to serve my web application.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Feature: Serve the PentaGram web application
  ...

  Scenario: Provision a fresh web host
    Given an empty host
    And the host is of type "pentagram-app"
    When I provision the host
    Then it should be running a web server
    And it should be responding to web requests
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Alright, I'm not supremeley thrilled with this approach, one such example is
that "pentagram-app" is a Puppet module, and I'm not very comfortable with that
leaky of an abstraction. So I'm going to reword it to: &lt;code&gt;And the host is a
PentaGram app host&lt;/code&gt; and start to define a vocabulary between my stake-holders
instead of letting Puppet module names leak upwards into Cucumber.&lt;/p&gt;

&lt;p&gt;The more I think about it, I'm not sure "developers" or even product-owners are the stake
holders to address with these features. As a developer, I care very little
about the operational details, so long as PentaGram works!&lt;/p&gt;

&lt;p&gt;Operations is its own compelling stake-holder, but that presents a complication
of making "outside-in" features such as these too leaky in terms of
abstractions and not very descriptive.&lt;/p&gt;

&lt;h3&gt;Operations as Stake Holders&lt;/h3&gt;

&lt;p&gt;That web host you provisioned above is nice and fancy and all that, but as far as I
am concerned (being a fellow Ops engineer), there's a lot more to an app host
than just running the web server.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Feature: Serve the PentaGram web application
  ...

  Scenario: Add app hosts into the load balancer
    Given a load balancer with a pool for app hosts
    And an empty PentaGram app host
    When I provision the host
    Then it should be added to the load balancer
    And it should be receiving requests from the load balancer
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I'm reasonably pleased with this, I'm going to pretend writing all these step
definitions is going to be rather easy to write, and forge ahead writing out
more Scenarios.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Scenario: Create the appropriate firewall rules
    Given an empty PengtaGram app host
    When I provision the host
    Then traffic should be allowed to port 80
    And traffic should be allowed to port 443

  Scenario: Nagios checks for app hosts
    Given a Nagios server
    And an empty PentaGram app host
    When I provision the host
    Then Nagios HTTP checks should be added for the host
    And Nagios HTTPs checks should be added for the host
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;At this point I've not written any step definitions or Ruby code to run these
Cucumber features, but I &lt;em&gt;think&lt;/em&gt; this enumerates what I want out of a PentaGram
app host.&lt;/p&gt;

&lt;p&gt;I know the following things are needed for an app host, just by reading
&lt;code&gt;apphost.feature&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A web server should be running (but how do we know it's not "It Works!"
coming from Apache instead of the PentaGram app?)&lt;/li&gt;
&lt;li&gt;The app host should be added to the load balancer's app-host pool when it is
provisioned&lt;/li&gt;
&lt;li&gt;The app host should port 80 and 443 open, ostensibly because Apache is
listening on those ports (we didn't say that it should be though! should we?)&lt;/li&gt;
&lt;li&gt;When the app host comes online, it should have Nagios checks added for its
service running on port 80 and port 443 (again, this doesn't verify the
PentaGram app is actually running there).&lt;/li&gt;
&lt;/ul&gt;


&lt;hr /&gt;

&lt;p&gt;I am not sure if this is the best approach, or even an approach that doesn't
suck, this entire blog post has been me riffing on what outside-in might look
like for Operations.&lt;/p&gt;

&lt;p&gt;In my next post on the subject, I should have some example code available with
fleshed out step definitions and some valid/passing scenarios.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/Xb8QSbPN0rA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/06/10/outside-in-to-ops.html</feedburner:origLink></entry>
 
 <entry>
   <title>Grok code with Puppet</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/OAkXx7x8Dpg/grokking-code-with-puppet.html" />
   <updated>2012-06-02T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/06/02/grokking-code-with-puppet</id>
   <content type="html">&lt;p&gt;As the &lt;a href="http://hackers.mylookout.com"&gt;Lookout&lt;/a&gt; code-base grows, both in
individual repositories but also in the sheer number of repos we maintain, I've
found it often difficult to find what I'm looking for.&lt;/p&gt;

&lt;p&gt;Some of that difficulty is due to ActiveRecord's determination to implement the
world through meta-programming, but for everything else I'm turning to
&lt;a href="http://www.opensolaris.org/os/project/opengrok/"&gt;OpenGrok&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OpenGrok itself is a Java-based code cross reference and search engine, which
works surprisingly well with Ruby. While not perfect, it certainly blew
&lt;a href="http://lxr.sourceforge.net/en/index.shtml"&gt;LXR&lt;/a&gt; away in both ease-of-use but
also cross-referencing of Ruby, Java, and C code.&lt;/p&gt;

&lt;p&gt;Below is an example of searching for the &lt;code&gt;AWS&lt;/code&gt; class in my
&lt;a href="https://github.com/rtyler/blimpy"&gt;Blimpy&lt;/a&gt; project.&lt;/p&gt;

&lt;center&gt;&lt;img src="http://strongspace.com/rtyler/public/opengrok-defsearch.png" alt="Searching for Definitions in OpenGrok"/&gt;&lt;/center&gt;


&lt;p&gt;You'll notice in the search results that there is a green-colored annotation to
the right of the code snippet denoting the actual definitions compared to other
search results.&lt;/p&gt;

&lt;p&gt;When I click on &lt;code&gt;aws.rb&lt;/code&gt; and dive into the code itself, I can navigate based on
method definitions, but also pull in &lt;code&gt;git-annotate(1)&lt;/code&gt; style annotations (not
pictured).&lt;/p&gt;

&lt;center&gt;&lt;img src="http://strongspace.com/rtyler/public/opengrok-methodnav.png" alt="Navigating code itself"/&gt;&lt;/center&gt;


&lt;hr /&gt;

&lt;p&gt;Since I'm no longer in the business of hand-crafting machines, I went ahead and
created &lt;a href="https://github.com/rtyler/puppet-opengrok"&gt;puppet-opengrok&lt;/a&gt;. This
OpenGrok Puppet module, while lacking in rspec-puppet tests (see
&lt;a href="https://twitter.com/glarizza"&gt;@glarizza&lt;/a&gt;, I'm a hypocrite), will allow you to
stand up a simple OpenGrok instance on an Ubuntu Server of your choosing.&lt;/p&gt;

&lt;p&gt;Take the following manifest for example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;node default {
  include opengrok

  opengrok::repo {
    "puppet" :
      git_url =&amp;gt; 'git://github.com/puppetlabs/puppet.git';
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The module will handle installing the packages &lt;code&gt;tomcat6&lt;/code&gt;, &lt;code&gt;git-core&lt;/code&gt; and a few
others to make things possible, but after you've run Puppet you can navigate
to: &lt;code&gt;http://yourhostname.lan:8080/source&lt;/code&gt; and you'll find OpenGrok has indexed
the Puppet code base for you!&lt;/p&gt;

&lt;p&gt;The module will also install a cronjob which updates the source trees and
indexes every 10 minutes.&lt;/p&gt;

&lt;p&gt;Currently &lt;a href="https://github.com/rtyler/puppet-opengrok"&gt;puppet-opengrok&lt;/a&gt; is quite
rough around the edges, since I used TDD (Tinker Driven Development) to build
it intead of TDD (Test Driven Development). It will most certainly work on
Ubuntu 10.04 LTS, but anywhere else your mileage may vary :)&lt;/p&gt;

&lt;p&gt;If you're familliar with &lt;a href="http://forge.puppetlabs.com"&gt;Puppet Forge&lt;/a&gt;, you can
install the &lt;a href="http://forge.puppetlabs.com/rtyler/opengrok"&gt;rtyler-opengrok&lt;/a&gt;
module with the &lt;code&gt;puppet-module&lt;/code&gt; tool.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/OAkXx7x8Dpg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/06/02/grokking-code-with-puppet.html</feedburner:origLink></entry>
 
 <entry>
   <title>Bullshit.</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/QxFgGsoNfhw/bullshit.html" />
   <updated>2012-05-30T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/05/30/bullshit</id>
   <content type="html">&lt;p&gt;"&lt;em&gt;Ruby on Rails is a full-stack web framework optimized for programmer happiness
and sustainable productivity. It encourages beautiful code by favoring
convention over configuration.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Almost nothing in that description describes any Rails code base I have ever
seen.&lt;/p&gt;

&lt;p&gt;(Taken from &lt;a href="http://rubygems.org/gems/rails"&gt;Ruby Gems.org&lt;/a&gt;)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/QxFgGsoNfhw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/05/30/bullshit.html</feedburner:origLink></entry>
 
 <entry>
   <title>Hub board: Call for testers</title>
   <link href="http://feedproxy.google.com/~r/UnethicalBlogger/~3/mB_ofFr7EQY/hubboard-call-for-testers.html" />
   <updated>2012-05-27T00:00:00-07:00</updated>
   <id>http://unethicalblogger.com/2012/05/27/hubboard-call-for-testers</id>
   <content type="html">&lt;p&gt;I've been working on &lt;a href="https://hubboard.herokuapp.com"&gt;Hub board&lt;/a&gt; off and on for
the past couple months, and I finally think it's ready for some more broad beta
testing.&lt;/p&gt;

&lt;p&gt;Hub board itself is meant to be a more visual Kan-ban style board built on top
of GitHub Issues. There are three states for issues "Open / Assigned", "In
Progress" and "Closed." By default Hub board will not show you any issues that
are not assigned to you; unfortunately there is not a means to assign existing
issues to yourself through Hub board &lt;a href="https://github.com/rtyler/Hubboard/issues/52"&gt;issue #52&lt;/a&gt;).&lt;/p&gt;

&lt;center&gt;&lt;a href="https://hubboard.herokuapp.com/intro" target="_blank"&gt;&lt;img src="http://strongspace.com/rtyler/public/hubboard-2012-05-27.png" alt="Hub board yay"/&gt;&lt;/a&gt;&lt;/center&gt;


&lt;p&gt;Please visit the &lt;a href="https://hubboard.herokuapp.com/intro"&gt;intro page&lt;/a&gt; to learn
more, and file &lt;a href="https://github.com/rtyler/Hubboard/issues"&gt;issues on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For the curious, Hub board is built with &lt;a href="http://amber-lang.net/"&gt;Amber
Smalltalk&lt;/a&gt; a JavaScript implementation of the Smalltalk
language and runtime. It is also built and deployed with the
&lt;a href="https://github.com/rtyler/resin"&gt;Resin&lt;/a&gt; which embeds Amber and couples it with
a simple Sinatra web server to make developing Amber applications exceptionally
easy.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/UnethicalBlogger/~4/mB_ofFr7EQY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://unethicalblogger.com/2012/05/27/hubboard-call-for-testers.html</feedburner:origLink></entry>
 

</feed>
