Ryan Kanno: The diary of an Enginerd in Hawaii

Everything you've ever thought, but never had the balls to say.

My LinkedIn Profile
Follow @ryankanno on Twitter
My Feed

Hello there, it’s been a while.

It’s been just over 4 years since my last blog.

Since we just moved to SF from NYC yesterday, today would be a good day to reflect on what’s been going in my life these past four years.

So even though we moved from the most amazing city in the world, yeah I just said it, I know there’s many more adventures to come.

Oh, and if you need NYC tips, feel free to ask.

(It kills me a little when I see where everyone ends up going. Hehe) :)

Tagged with ,

For the Horde – DIY World of Warcraft Brownies

For the Horde – DIY World of Warcraft Brownies

I noes I haven’t updated my blog in a few months more than a year, but I’ve been busy working at a small, local news startup. Since one of my New Year’s resolutions was to be a more diligent blogger, I thought I would start this year off with a *whiz-bang*, non-technical post!

(I guess it’s pretty ironic that I’m posting this in January August, huh? :D)

Last December, I was invited to a Christmas Party. Not your standard-fare holiday party, mind you, but a “World of Warcraft Guild” Christmas Party. Wanting to bring something unique to the potluck, I ended up making “For The Horde Brownies”… and this is a blog detailing the experience.

›› Setup

  • Your favorite brownie mix/recipe
  • Powdered sugar
  • Print out of the For the Horde pdf
  • X-Acto knife (or scissors)

›› Baking the brownies

I’ll be the first to admit that I’m no baker. While there are those that profess it as their passion, I see it purely as a means to an end. With that said, you can use <insert your favorite brownie mix here> to make the brownies or if you’re feeling exceptionally adventurous, maybe use one of these recipes. Whatever your poison, just make sure it appears edible – enough to trick your guests with; kind of like this.

Your favorite brownie mix

The magical concoction!

Pulling the wool over sheep's eyes


›› Preparing the Horde symbol

While baking your magical brownies, print out the enclosed Horde pdf. You’ll want to make a few copies to practice your X-Acto skills on. Of course, if your scissor-fu is amazing, feel free to wield those instead. (It took me two tries with the X-Acto to get it just right). After you’ve finished removing the Horde symbol, it should resemble the following:

Horde symbol

Horde symbol cutout


›› For the Horde!

After you have a cut out of the Horde symbol, you can use the powdered sugar to apply the symbol to your brownies. If you mess up, like I did, fret not.

Pro-tip: if the powdered sugar goes awol, use some water to dissolve the sugar and clean up the edges.

Practice Run

Applying the symbol


Your final product should end up looking something like the following:

For the Horde



›› Credits

As usual, I must give props where props are due.

People I owe a soul to

Tagged with

Update: Using Capistrano 2.5 to deploy Rails 2.3 to Webfaction


Having been a Capistrano user for a few years, I absolutely love sweet, sweet automation. A few months ago, I wrote a blog about how to use Capistrano to deploy to WebFaction. However, since that post, the winds of change have swept through the Rails and Capistrano community with the release of Rails 2.3 and Capistrano 2.5. WebFaction’s Ruby installation precludes you from taking advantage of these great updates, so I’ve come up with a little update to my previous post.

Learn to Change, Change to Learn

To be able to deploy Rails 2.3 with Capistrano 2.5, we’ll first have to jump through a few hoops. Nice, easy hoops, mind you, but still hoops nonetheless.

Your own Ruby installation

You’ll have to install a custom Ruby installation into your WebFaction home directory. By following Step 1 here, you’ll have a working Ruby 1.8.7 installation and RubyGem 1.3. You’ll need these if you want to deploy a Rails 2.3 application. Also, install a version of Mongrel tied to your Ruby installation.

Note: Typically, I like to install custom installations into ~/opt/local/lib/.

Edit Autostart.cgi

You’ll have to make a few edits to a few files from my previous blog post.

Next, open up your favorite editor of choice (*cough*vi*cough*) and edit the autostart.cgi file. Jump to the end of the file and comment out the following line from my previous blog:

# os.system('/usr/local/bin/mongrel_rails start -c /home/<webfaction_username>/webapps-releases/<webfaction_app_name>/current -d -e production -P /home/<webfaction_username>/webapps/<webfaction_app_name>/log/mongrel.pid -p <port>')

and change it to the following:

 os.system('/home/<webfaction_username>/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails start -c /home/<webfaction_username>/webapps-releases/<webfaction_app_name>/current -d -e production -P /home/<webfaction_username>/webapps/<webfaction_app_name>/log/mongrel.pid -p <port>')

Notice: We’re using the path to Mongrel tied to our custom Ruby installation! This might be different in your installation!

Edit the Capfile

In my previous blog, we placed a custom deploy.rb into the config directory. With the latest version of Capistrano, you no longer need to do this. Rather, place the following into a file called Capfile in the root of your Rails project.

load 'deploy'
set :webfaction_username, "<webfaction_username>"
set :webfaction_db_type, "<webfaction_db_type>"
set :webfaction_db, "<webfaction_db>"
set :webfaction_db_username, "<webfaction_db_username>"
set :webfaction_port, "<webfaction_port (get from autostart.cgi)>"
set :database_yml_template, "database.example.yml"
set :application, "test"
set :deploy_to, "/home/#{webfaction_username}/webapps-releases/#{application}"
set :scm, :subversion
set :scm_user, "<scm_username>"
set :scm_password, Proc.new { Capistrano::CLI.password_prompt("Subversion password for #{scm_user}: ") }
set :repository, Proc.new { "--username #{scm_user} --password #{scm_password} --no-auth-cache <http://path/to/your/svn/goes/here/>"} 
set :user, "#{webfaction_username}"
set :use_sudo, false 
set :domain, "<webfaction_domain>"
role :app, domain
role :web, domain
role :db,  domain, :primary => true
desc "Symlink public to what webfaction expects the webroot to be"
task :after_symlink, :roles => :web do
  run "ln -nfs #{release_path}/public /home/#{webfaction_username}/webapps/#{application}/"
namespace :deploy do
  # Taken from http://jonathan.tron.name/2006/07/15/capistrano-password-prompt-tips 
  # Thanks Jonathan! :)
  desc "Creates the database configuration on the fly"
  task :create_database_configuration, :roles => :app do
    require "yaml"
    set :production_db_password, proc { Capistrano::CLI.password_prompt("Remote production database password: ") }
    db_config = YAML::load_file("config/#{database_yml_template}")
    db_config['production']['adapter'] = "#{webfaction_db_type}"
    db_config['production']['database'] = "#{webfaction_db}"
    db_config['production']['username'] = "#{webfaction_db_username}"
    db_config['production']['password'] = production_db_password
    db_config['production']['host'] = "localhost"
    put YAML::dump(db_config), "#{release_path}/config/database.yml", :mode => 0664
  after "deploy:update_code", "deploy:create_database_configuration"
  desc "Redefine deploy:start"
  task :start, :roles => :app do
    invoke_command "/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails start -c #{deploy_to}/current -d -e production -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid -p #{webfaction_port}", :via => run_method
  desc "Redefine deploy:restart"
  task :restart, :roles => :app do
    invoke_command "/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails restart -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid", :via => run_method
  desc "Redefine deploy:stop"
  task :stop, :roles => :app do
    invoke_command "/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails stop -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid", :via => run_method
Note: Change all the values in tags like <webfaction_username>, <webfaction_db>, <webfaction_db_username>, etc. to those values that fit your configuration!
Otherwise, this file in itself won’t do you any good.

Now, you should be able to run the standard Capistrano tasks to deploy your application to WebFaction with the latest version of Rails!


Basically, the only thing I’ve done is shown you how to update your version of Ruby, RubyGems, Mongrel, and Capistrano to place nicely in WebFaction. This should allow you to run commands like ‘cap deploy:setup’, ‘cap deploy:update’ on your local machine and update your live code on WebFaction’s servers. Nothing too serious going on here! As always, feel free to use, steal, take, and/or copy anything on this blog. Hopefully somewhere, someone on the Interwebs will find these tips handy!

And if you find anything wrong with these scripts, don’t hesitate to leave a comment or email!

Voila! (Enjoy)

Tagged with , , , ,

Lessons Learned: Google App Engine + App Engine Patch + Django + Boto


Mitch Garnaat from CloudRight has pointed out that you can actually set the policy of the S3 file in the set_contents_from_file call instead of making another roundtrip request into S3 (and saving you some coin). Thanks Mitch!

Btw, I’m using App Engine Patch 1.0 and Boto 1.6a.

Sorry I haven’t updated my blog in a few weeks months, but I’ve been a little busy. With that said, along with Erlang, I’ve been playing around with Google App Engine, App Engine Patch (for Django support), and the Boto library (for Amazon S3 support). After not having touched Python code in a few months, I wanted to document some of my lessons learned to help over developers who may be in a similar boat.

Lessons learned

  • If you’re upgrading the App Engine Patch, make sure you don’t have the App Engine library installed in a hidden directory
  • Uploading bulk data changed ever so slightly
  • If you’re not running off of Boto’s trunk, you’ll need to patch your Boto installation to work with App Engine.

Make sure the App Engine library isn’t installed in a hidden directory

Apparently, Google’s SDK 1.1.9 doesn’t like to rely on files that won’t be uploaded with your application – and hidden directories are no longer uploaded. I was running into the dreaded purple-nurple screen of death. Thank goodness for this AppEngine Google Group post, but I’m still not even sure when this popped up considering Google’s articles still refer to this setup.

Bulk upload

Compared to the previous SDK I was playing around with, bulk uploading changed significantly. I recall having to patch Goog’s bulkupload.py file to get unicode support. However, their new remote api tool has definitely fixed this issue, so +1 for Googs. People are reporting that uploading unicode is still broken, but it’s not. Or at least it wasn’t for me. Second, if you’re like me and don’t read documentation, you’ll find out (the hard way) that the method signature to HandleEntity changed. Instead of accepting a datastore.Entity, it’s now expecting a db.Model object.

Note: When actually running the remote api tool, you’ll also want to make sure your PYTHONPATH includes your current project. (Another one-liner in the documentation. :P)

Integrating Boto + App Engine

I wasn’t running off of Boto’s trunk and I was getting an obscure type conversion error. Being too lazy to check out the source, I jumped to their issue tracker and found a patch (halfway down the page) by one of the App Engine Patch lead devs. Apply the patch and you’ll be on your way to uploading images/data from App Engine into Amazon S3! If you’re looking for example code, I’ve included a small snippet of what I tested.

    def upload_to_s3(original_filename, photo):
        """ Upload a photo file, storing its original name as metadata in an S3 bucket """
        connection = Connection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY)
        bucket = connection.get_bucket(settings.AWS_IMAGE_BUCKET_NAME)
        photo_uuid = str(uuid.uuid4())
        new_key = Key(bucket)
        new_key.key = photo_uuid
        new_key.set_metadata('original_filename', original_filename)
        new_key.set_contents_from_file(photo, policy='public-read')
        return photo_uuid

Note: I only tested the code above with small images ~300-500K in size and it seemed to work perfectly fine (with no load! :P). As always, feel free to use, steal, take, and/or copy anything on this blog. Hopefully somewhere, someone on the Interwebs will find these tips handy!


Tagged with , , , , ,

Seven Things Meme aka Damn you, Harper Reed!

Internet memes rock my socks!

Unfortunately, I was tagged by Harper for a “7 things” meme where I have to divulge seven tidbits of randomness about myself. I’m generally not a big fan of these things since most of you on the Interweb could care less about me, but it is Harper… and well, he is my new bicycle, so here goes:

1. I have “girlie” handwriting

I blame this 1000% all on my sister. Throughout the years, people have told me that I write like a girl – whatever that means. I don’t know how many days of my childhood I spent playing “school”, but it’s quite apparent that it was damn too many. Thanks Stace!

2. I used to play an inordinate amount of video games

They say a picture is worth a thousand words, but this one just might make you speechless. Damn you, John Carmack, for making one of the greatest games of my generation and *almost* failing me out of college. I’ve just recently been sucked into this wonderful World of Warcraft. God, help me.

3. I

Whether it’s the crosswords, sudoku, kakuro, chess, or that damn Bejeweled, I absolutely love puzzles. I typically have a really short attention span, but puzzles have known to captivate me for hours on end.

4. I am ultra-competitive

I don’t know if it was the math games my mom challenged me with as a child, but I’m probably on the extremely far end of the competitiveness scale. It could be eating (grr, Kobayashi, here I come), games at Dave and Buster’s, or just a game of pickup basketball, I’ll compete at anything. And if you’re lucky, I’ll probably throw in some trash talking as well.

5. I am a total sucker for 80’s cartoons

Whether it’s G.I. Joe, Transformers, M.A.S.K., Thundercats, Voltron, or Silverhawks; I’m an uber 80’s cartoon fan. I don’t know if I should be admitting this as a 30 year old, but I have an extensive collection of Transformers and G.I. Joes safely stored away at my parent’s house. Thanks, Mom & Dad!

6. I love to read

I’m not sure when this happened in my life, but I’ve come to love reading. When I was younger, I absolutely loved Encyclopedia Brown and the Choose Your Own Adventure series. As I’ve gotten older, I’ve stuck to the more non-fiction variety, and I’m currently working on these books here. One of these days, I’m hoping someone will get me an Amazon Kindle. =P (*hint* *hint*)

7. Hi, my name is Ryan, and I’m a caffeine Coke Zero addict

Since my parents never allowed me to drink caffeine as a child, I don’t know exactly when this happened. It could have been all those all-nighters in grad school trying finish up the last bits of code, or the late nights playing online games. In any case, I drink a six pack a day, on the conservative estimate, but I’m really, really trying to stop. I think.


And there you have it folks – a few lame tidbits about me. Now, according to Harper, to make this official, I have to tag 7 other unfortunate online souls. So… I tag:

  • Ed S – I met Ed through a basketball league, and it just so happens we share a similar interest in all things technology. Not only does he manage one of the larger media sites in Hawaii, but he is also a featured blogger @ the Honolulu Advertiser.
  • Stephen F – A former co-worker, I’m hoping that this will kick-start his blogging. Since he’s busy with kids, school, and work, I’m not sure he’ll have time for this, but hey, it’s worth a try. He knows all things .Net and Ruby.
  • Kevin M – We met during our freshman year at U of I in calculus. He’s a .Net machine working for Clarity Consulting and is full of zany ideas. He was even featured on Microsoft’s Coding4Fun for his DIY foosball hack. I’m sure he’ll have something great to write.
  • Greg Y – We used to work in the same organization, and I’d help him out with small projects. He’s leading the Hawaii Web 2.0 charge in the organization and also masquerades as a part-time blogger @ Pulp Connection.
  • Mark Q – One of my current co-workers who knows all things CSS and Mac. He’s a Symfony user *cough*fanboy*cough* and is currently trying to convince me to switch over to the darkside. “Resistance is futile.
  • Scott V – We met during our freshman year at U of I playing what else but Quake. Not only is he half man, half crazy, but he’s also the nerdvana of all things system administration. He currently works at Threadless with Harper causing all sorts of havoc.
  • Trent N – I mentored Trent through HiTechQuest. He’s a young’un but has all types of technological potential. Since he’s the youngest I’ve tagged, I’m sure he’ll have all sorts of interesting things to teach us old folk.

And if you’re one of the chosen ones, here are the rules:

  • Link your original tagger(s), and list these rules on your blog.
  • Share seven facts about yourself in a post – some random, some weird.
  • Tag seven people at the end of your post by leaving their names and the links to their blogs.
  • Let them know they’ve been tagged by leaving a comment on their blogs and/or Twitter

Tagged with , , , , , , , ,

Powered by Wordpress. Stalk me.