<?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>Silas Sewell - Projects</title>
        <atom:link href="http://www.silassewell.com/blog/tag/projects/rss2.xml" rel="self" type="application/rss+xml" />
        <link>http://www.silassewell.com/blog/tag/projects</link>
        <description>Infrastructure Development</description>
        <lastBuildDate>Sat, 08 Jan 2011 00:00:00 GMT</lastBuildDate>
        <generator>http://www.silassewell.com/</generator>
        <language>en</language>
        <sy:updatePeriod>hourly</sy:updatePeriod>
        <sy:updateFrequency>1</sy:updateFrequency>

        <item>
            <title>Google App Engine Middleware (gaem)</title>
            <link>http://www.silassewell.com/blog/2009/12/29/google-app-engine-middleware-gaem/</link>
            <pubDate>Tue, 29 Dec 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Fedora]]></category><category><![CDATA[gaem]]></category><category><![CDATA[Google]]></category><category><![CDATA[Google App Engine]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Python]]></category><category><![CDATA[Reverse Proxy]]></category><category><![CDATA[Software]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/12/29/google-app-engine-middleware-gaem/</guid>
            <description><![CDATA[<p><a href="http://github.com/silas/gaem" title="Google App Engine Middleware">Google App Engine Middleware</a> (gaem) is a collection of utilities for
hosting external sites on Google App Engine.</p>

<p>I created gaem because I wanted to host my blog on an unreliable server and let
Google App Engine serve the content while my server was down or in maintenance
mode.</p>

<p>The basic design is similar to that of <a href="http://docs.djangoproject.com/en/dev/topics/http/middleware/" title="Django's middleware">Django's middleware</a>. A request
travels through a list of components which can either manipulate the request or
provide a response. The response is filtered back through the components and
served to the requester.</p>

<p>A basic implementation looks something like</p>

<pre><code class="prettyprint">import gaem
import gaem.middleware
import gaem.middleware.cache
import gaem.middleware.dos
import gaem.middleware.fetch

URL = 'http://www.example.org'

MIDDLEWARE_CLASSES = (
    gaem.middleware.cache.Memcache(),
    gaem.middleware.cache.Datastore(),
    gaem.middleware.dos.DoS(),
    gaem.middleware.fetch.Fetch(url=URL),
)

application = gaem.Application(MIDDLEWARE_CLASSES)

if __name__ == '__main__':
    application.run()
</code></pre>

<p>When a request first hits this application it is handled by the Memcache
component. This basic caching component checks the Google App Engine Memcache
service to see if the page is in the cache. If so it simply returns the cached
response, otherwise the request proceeds to the Datastore component which does
pretty much the same thing except it uses Google Datastore for persistence. If
both caching components fail the the request goes through a DoS protection
component and is finally retrieved from the backend server by the Fetch
component.</p>

<p>Using a setup like this gaem acts as a rudimentary reverse proxy and while most
of the functionality I've implemented thus far is for this type setup, I plan
on adding features not traditionally found in a reverse proxy.</p>

<h3>Current Features</h3>

<ul>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/cache.py" title="Caching">Caching</a></li>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/fetch.py" title="Backend fetch">Backend fetch</a></li>
<li>Gracefully handle a dead backend</li>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/dos.py" title="DoS protection">DoS protection</a></li>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/api.py" title="API for expiring content">API for expiring content</a></li>
</ul>

<h3>Possible Future Features</h3>

<ul>
<li>Initial and periodic crawler (pre-cache and other hooks)</li>
<li>RESTful API for managing content (put, delete, etc...)</li>
<li>Web interface</li>
<li>XSS protection</li>
<li>Some ESI support</li>
</ul>

<p>But what makes gaem really cool for developers is how easy it is to create
custom components.</p>

<p>A basic component looks like</p>

<pre><code class="prettyprint">from gaem import middleware

class DoesNothing(middleware.Base):

    def process_request(self, request):
        return request

    def process_response(self, response, request):
        return response
</code></pre>

<p>A default gaem component should inherit from <code class="prettyprint">gaem.middleware.Base</code> and
implement <code class="prettyprint">process_request</code> and/or <code class="prettyprint">process_response</code>.</p>

<p>The <code class="prettyprint">process_request</code> function lets you either manipulate the request (ex:
strip the "cookie" header) and pass it along or use the request to create and
return a response (ex: do a fetch to the backend server). The
<code class="prettyprint">process_response</code> function lets you filter the response (ex: translate body
into pig latin) and do side affects (ex: store response in memcache) before the
response is sent to the requester.</p>

<p>The Request/Response objects are borrowed from <a href="http://pythonpaste.org/webob/" title="WebOb">WebOb</a> and can be
manipulated using the interfaces defined in the <a href="http://pythonpaste.org/webob/modules/webob.html" title="WebOb documentation">WebOb documentation</a>.</p>

<p>gaem is currently pretty rough and likely to change over the next couple of
months, but if you're a Python hacker I'd love to hear some feedback
(<a href="http://www.silassewell.com/about/contact/" title="Contact Silas Sewell">contact me</a> or <a href="http://github.com/silas/gaem/issues" title="gaem issues">submit an issue</a>).</p>

<p>P.S. You can see the application I created for this site in the <a href="http://github.com/silas/gaem/tree/master/examples/wordpress/" title="gaem WordPress example">examples directory</a>.</p>]]></description>
        </item>

        <item>
            <title>Stomping with Python and ActiveMQ (Stomp Framework)</title>
            <link>http://www.silassewell.com/blog/2009/08/27/stomping-with-python-and-activemq-stomp-framework/</link>
            <pubDate>Thu, 27 Aug 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[ActiveMQ]]></category><category><![CDATA[Fedora]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Python]]></category><category><![CDATA[python-stomping]]></category><category><![CDATA[STOMP]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/08/27/stomping-with-python-and-activemq-stomp-framework/</guid>
            <description><![CDATA[<p><a href="http://silassewell.googlecode.com/svn/trunk/projects/python-stomping" title="Python Stomping">python-stomping</a> is a simple <a href="http://en.wikipedia.org/wiki/Streaming_Text_Orientated_Messaging_Protocol" title="Stomp">Stomp</a> framework I wrote which makes
creating stomp services in Python easy.</p>

<ol>
<li><p>Install requirements</p>

<pre><code class="prettyprint">$ sudo yum install python-twisted python-stomper
</code></pre></li>
<li><p>Checkout stomping</p>

<pre><code class="prettyprint">$ svn export http://silassewell.googlecode.com/svn/trunk/projects/python-stomping python-stomping
$ cd python-stomping
</code></pre></li>
<li><p>Update the <code class="prettyprint">example.py</code> file to use your <code class="prettyprint">host</code>, <code class="prettyprint">port</code>, <code class="prettyprint">username</code> and
<code class="prettyprint">password</code> ActiveMQ/Stomp broker settings</p>

<pre><code class="prettyprint">from stomping import Stomping, route

class MyStomping(Stomping):

def init(self):
    self.send('/queue/test1', 'init test1')
    self.send('/queue/test2', 'init test2')

@route('/queue/test1')
def a_test(self, message):
    print 'a_test: %s' % message['body']

@route('/queue/test1')
@route('/queue/test2')
def b_test(self, message):
    print 'b_test: %s' % message['body']

if __name__ == '__main__':
    stomp = MyStomping(host='127.0.0.1', port=61613, username='guest', password='guest')
    stomp.run()
</code></pre></li>
<li><p>Run <code class="prettyprint">example.py</code> (Ctrl+c to quit)</p>

<pre><code class="prettyprint">$ python example.py 
a_test: init test1
b_test: init test1
b_test: init test2
</code></pre></li>
</ol>

<p>NOTE: python-stomping is just a light wrapper around Twisted and stomper and is
based on an <a href="http://code.google.com/p/stomper/source/browse/trunk/lib/stomper/examples/sender.py" title="sender example">example</a> provided in the stomper code.</p>]]></description>
        </item>

        <item>
            <title>funcshell — A Shell Interface to Func</title>
            <link>http://www.silassewell.com/blog/2009/04/22/funcshell-a-shell-interface-to-func/</link>
            <pubDate>Wed, 22 Apr 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Fedora]]></category><category><![CDATA[Func]]></category><category><![CDATA[FuncShell]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Systems Administration]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/04/22/funcshell-a-shell-interface-to-func/</guid>
            <description><![CDATA[<h3>Features</h3>

<ul>
<li>advanced client selection (you can use + and - to add/remove hosts/groups)</li>
<li>tab completion</li>
<li>persistent history</li>
<li>a command sub-shell</li>
<li>quick help (just hit the "?" key)</li>
</ul>

<p><strong>funcshell</strong> took a similar approach to features as Func; it allows developers to easily extend and customize its functionality using a plugin system. It also assumes the most useful commands will be the ones you write yourself. That being said, funcshell currently comes with both the command and service module.</p>

<p>Here are some things you can do with funcshell.</p>

<p>Get a list of all clients (not very useful if you have hundreds):</p>

<pre><code class="prettyprint">funcshell&gt; set clients *
funcshell&gt; get clients
webapp001.example.net
webapp002.example.net
webapp003.example.net
webstatic001.example.net
webstatic002.example.net
</code></pre>

<p>Assuming <code class="prettyprint">webapp00[1-3].example.net</code> are in the <code class="prettyprint">app</code> and <code class="prettyprint">bpstatic00[1-2].example.net1</code> are in the <code class="prettyprint">static</code> groups; remove some clients and restart a service:</p>

<pre><code class="prettyprint">funcshell&gt; set clients - @static;webapp001*
funcshell&gt; get clients
webapp002.example.net
webapp003.example.net
funcshell&gt; service httpd restart
==&gt; webapp003.example.net &lt;==
True
==&gt; webapp002.example.net &lt;==
True
</code></pre>

<p>Run a command and get the results:</p>

<pre><code class="prettyprint">funcshell&gt; set clients - webapp003*
funcshell&gt; set clients + webstatic002*
funcshell&gt; command run grep MemTotal /proc/meminfo | awk '{ print $2/1024 }'
==&gt; webstatic002.example.net :: 0 &lt;==
4099.44
==&gt; webapp002.example.net :: 0 &lt;==
8198.88
</code></pre>

<p>Get help:</p>

<pre><code class="prettyprint">funcshell&gt; command &lt;TAB&gt;&lt;TAB&gt;
exists   run      shell
funcshell&gt; command ?
  exists Check if a command exists
  run    Run a command
  shell  Run a command shell
</code></pre>

<p>Run a couple of commands in a row:</p>

<pre><code class="prettyprint">funcshell&gt; set c&lt;TAB&gt; @static
funcshell&gt; command shell
&gt; du -sh /tmp
==&gt; webstatic002.example.net :: 0 &lt;==
7.2M    /tmp
==&gt; webstatic001.example.net :: 0 &lt;==
3.4M    /tmp
&gt; cp -r /tmp /tmp
==&gt; webstatic002.example.net :: 1 &lt;==
cp: cannot copy a directory, '/tmp', into itself, '/tmp/tmp'
==&gt; webstatic001.example.net :: 1 &lt;==
cp: cannot copy a directory, '/tmp', into itself, '/tmp/tmp'
&gt; asdf
==&gt; webstatic002.example.net :: 127 &lt;==
/bin/sh: asdf: command not found
==&gt; webstatic001.example.net :: 127 &lt;==
/bin/sh: asdf: command not found
&gt; &lt;CTRL-D&gt;
funcshell&gt; exit
</code></pre>

<p><a href="http://github.com/silas/funcshell" title="funcshell">funcshell</a> is a shell interface to <a href="https://fedorahosted.org/func/" title="func">Func</a> which provides some useful features for managing a large number of machines.</p>]]></description>
        </item>

        <item>
            <title>Profile Management with Git and GitHub</title>
            <link>http://www.silassewell.com/blog/2009/03/08/profile-management-with-git-and-github/</link>
            <pubDate>Sun, 08 Mar 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Bash]]></category><category><![CDATA[Configuration Management]]></category><category><![CDATA[Git]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Systems Administration]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/03/08/profile-management-with-git-and-github/</guid>
            <description><![CDATA[<p>The following describes a simple way to manage you profile configuration files using GitHub.</p>

<h3>Features</h3>

<ul>
<li>Centralized configuration management</li>
<li>Files live in their native locations (no symbolic linking)</li>
<li>Home directory is not a Git repository</li>
<li>All the power of git with a simple alias</li>
</ul>

<h3>Setup Repository</h3>

<ul>
<li>Log into <a href="http://github.com/" title="GitHub">GitHub</a> and create a repository named config</li>
<li>Add your <a href="http://github.com/guides/providing-your-ssh-key" title="Public Keys to GithHub">public keys to GitHub</a> (if you haven't done so already)</li>
<li><p>Open a terminal and switch to your home directory</p>

<pre><code class="prettyprint">cd ~
</code></pre></li>
<li><p>Create a configuration directory</p>

<pre><code class="prettyprint">mkdir .config.git
</code></pre></li>
<li><p>Add the following alias to your current session and your <code class="prettyprint">.bash_profile</code></p>

<pre><code class="prettyprint">alias config='git --git-dir=$HOME/.config.git/ --work-tree=$HOME'
echo "alias config='git --git-dir=$HOME/.config.git/ --work-tree=$HOME'" &gt;&gt; .bash_profile
</code></pre></li>
<li><p>Add your <code class="prettyprint">.bash_profile</code> to the configuration repository</p>

<pre><code class="prettyprint">config add .bash_profile
</code></pre></li>
<li><p>Commit the changes</p>

<pre><code class="prettyprint">config commit -m 'Initial commit'
</code></pre></li>
<li><p>Change the origin to GitHub</p>

<pre><code class="prettyprint">config remote add origin git@github.com:GITHUB_USERNAME/config.git
</code></pre></li>
<li><p>Push the changes</p>

<pre><code class="prettyprint">config push origin master
</code></pre></li>
</ul>

<p>If you get an error when running <code class="prettyprint">config pull</code> to the effect of <code class="prettyprint">You asked me to pull without...</code> run the follow:</p>

<pre><code class="prettyprint">    echo -e '[branch "master"]\n  remote = origin\n  merge = refs/heads/master' &gt;&gt; ~/.config.git/config
</code></pre>

<h3>Setup Configuration Management on a Different System</h3>

<ol>
<li>Add your <a href="http://github.com/guides/providing-your-ssh-key" title="Public Keys to GithHub">public keys to GitHub</a> (if you haven't done so already)</li>
<li><p>Switch to your home directory</p>

<pre><code class="prettyprint">cd ~
</code></pre></li>
<li><p>Backup your local configuration files, example:</p>

<pre><code class="prettyprint">mv .bash_profile .bash_profile.bk
</code></pre></li>
<li><p>Clone your configuration repository</p>

<pre><code class="prettyprint">git clone git@github.com:GITHUB_USERNAME/config.git config.git
</code></pre></li>
<li><p>Move the git metadata to <code class="prettyprint">~/.config.git</code></p>

<pre><code class="prettyprint">mv config.git/.git .config.git
</code></pre></li>
<li><p>Enable dotglob</p>

<pre><code class="prettyprint">shopt -s dotglob
</code></pre></li>
<li><p>Move your configuration files to your home directory</p>

<pre><code class="prettyprint">mv -i config.git/* .
</code></pre></li>
<li><p>Delete the <code class="prettyprint">config.git</code> directory</p>

<pre><code class="prettyprint">rmdir config.git
</code></pre></li>
<li><p>Logout and log back in</p></li>
</ol>

<h3>Basic Usage</h3>

<ul>
<li><code class="prettyprint">config pull</code> - get latest configuration changes</li>
<li><code class="prettyprint">config add FILENAME</code> - add a configuration file</li>
<li><code class="prettyprint">config commit -a</code> - save all configuration changes</li>
<li><code class="prettyprint">config push</code> - push configuration changes to GitHub</li>
<li>and any other <code class="prettyprint">config GIT_OPTION</code></li>
</ul>

<p>You can see my configuration repository at <a href="http://github.com/silas/config" title="config">http://github.com/silas/config</a>.</p>

<p>Source: <a href="http://robescriva.com/2009/01/manage-your-home-with-git/" title="source">Manage your $HOME with git</a> by Robert Escriva</p>]]></description>
        </item>

        <item>
            <title>Introducing the FuncShell</title>
            <link>http://www.silassewell.com/blog/2009/01/30/introducing-the-func-shell/</link>
            <pubDate>Fri, 30 Jan 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Func]]></category><category><![CDATA[Func Shell]]></category><category><![CDATA[FuncShell]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Python]]></category><category><![CDATA[Systems Administration]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/01/30/introducing-the-func-shell/</guid>
            <description><![CDATA[<p><strong>Update</strong>: I am currently refactoring FuncShell; please use the following
code: <a href="http://github.com/silas/funcshell/raw/f630b9dd552287f5fe4b3f46ca09442499c68f0f/src/shell.py" title="shell.py">shell.py</a>.</p>

<p>I created <a href="http://github.com/silas/funcshell" title="funcshell">funcshell</a> for running <a href="https://fedorahosted.org/func/" title="func">Func</a> modules in a more
intuitive manner.</p>

<p>The current implementation only supports the command module, but more will be
released shortly.</p>

<p><strong>Code:</strong> <a href="http://github.com/silas/funcshell" title="funcshell">http://github.com/silas/funcshell</a></p>

<h3>Example Usage</h3>

<pre><code class="prettyprint">[root@pluto ~]# python shell.py
fs&gt; use web*.example.org
fs&gt; get hosts
web01.example.org
web02.example.org
fs&gt; !du -sh /tmp
================================================================================
== web02.example.org                                                          ==
================================================================================

236K    /tmp

================================================================================
== web01.example.org                                                          ==
================================================================================

217M    /tmp

fs&gt; !cat /proc/meminfo | grep MemTotal | awk '{ print $2 }'
================================================================================
== web02.example.org                                                          ==
================================================================================

1027116

================================================================================
== web01.example.org                                                          ==
================================================================================

1027116

fs&gt; exit
[root@pluto ~]#
</code></pre>]]></description>
        </item>

        <item>
            <title>Common Usage Database (cudb)</title>
            <link>http://www.silassewell.com/blog/2008/09/24/common-usage-database-cudb/</link>
            <pubDate>Wed, 24 Sep 2008 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[CLI]]></category><category><![CDATA[Common Usage Database]]></category><category><![CDATA[Projects]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2008/09/24/common-usage-database-cudb/</guid>
            <description><![CDATA[<p>A couple of months ago I was searching for an excuse to write an application on
Google App Engine. After mucking around with the <a href="http://code.google.com/appengine/docs/datastore/" title="Datastore">Datastore</a> and
<a href="http://code.google.com/appengine/docs/users/" title="User Authentication">authentication</a> API I decided to rewrite Most Common Usage on Google
App Engine.</p>

<p>The end result was the <a href="http://www.cudb.org/">Common Usage Database</a> and like Most Common
Usage the website is focused on the usage of CLI commands in Linux and
Unix-like operating systems.</p>

<p>The website uses Google for authentication so you don't need to signup if you
already have a Google account. I've also setup a <a href="http://groups.google.com/group/cudb">Google Group</a> and the
<code class="prettyprint">#cudb</code> channel on Freenode.</p>

<p>I look forward to creating a repository of useful commands and providing an
easy and open way for developers to use that repository.</p>

<p>Link: <a href="http://www.cudb.org/">http://www.cudb.org/</a></p>]]></description>
        </item>

        <item>
            <title>Python SDK for PhoneFactor</title>
            <link>http://www.silassewell.com/blog/2008/06/07/python-sdk-phonefactor/</link>
            <pubDate>Sat, 07 Jun 2008 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[PhoneFactor]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Python]]></category><category><![CDATA[SDK]]></category><category><![CDATA[Security]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2008/06/07/python-sdk-phonefactor/</guid>
            <description><![CDATA[<p>A first (and very alpha) attempt at creating a Python SDK for <a href="http://www.phonefactor.com/" title="PhoneFactor">PhoneFactor</a>.</p>

<p>Link: <a href="http://github.com/silas/graveyard/tree/master/python-phonefactor/" title="Python PhoneFactor">http://github.com/silas/graveyard/tree/master/python-phonefactor/</a></p>]]></description>
        </item>

        <item>
            <title>Post a Get</title>
            <link>http://www.silassewell.com/blog/2008/03/30/post-a-get/</link>
            <pubDate>Sun, 30 Mar 2008 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Firefox]]></category><category><![CDATA[Keywords]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Projects]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2008/03/30/post-a-get/</guid>
            <description><![CDATA[<p>I've created a PHP script called <a href="http://www.silassewell.com/blog/2008/03/30/post-a-get/index.php" title="Post a Get">Post a Get</a> which can be copied to
any PHP capable server and used to created a POST request using GET syntax.</p>

<p>Let's say you use GoDaddy as your domain registrar and you would like to see if
a domain is available using Firefox keywords, but they don't offer a GET
search.</p>

<p>For a traditional keyword, you could construct a GET request like:</p>

<pre><code class="prettyprint">https://www.godaddy.com/gdshop/registrar/search.asp&amp;checkAvail=1&amp;fblur=1&amp;tld=.com&amp;domainToCheck=%s
</code></pre>

<p>But as of right now Firefox doesn't offer a way to create POST keywords. What
Post a Fix does is allow you to construct a POST request using GET syntax and
pass it to the <a href="http://www.silassewell.com/blog/2008/03/30/post-a-get/index.php" title="Post a Get">Post a Get code</a>.</p>

<p>So if you wanted to submit the above GET as a POST, you would construct the URL
and append the special __action parameter with target URL. So the final URL
would look something like:</p>]]></description>
        </item>

    </channel>
</rss>
