Narnach's blog

The thoughts of Wes "Narnach" Oldenbeuving

SimpleGate

At yoMedia we frequently have to perform simple tasks on servers that are only reachable by hopping through a number of other servers. To deploy Rails, Merb or Ruby projects, we use Capistrano and it works great. It is easy to configure and you can set it to use any number of gateway servers if that is needed to reach a server.

When deploying ruby gems or executing arbitrary commands, Capistrano does not really work for me. Don’t get me wrong, the upload:deploy task is great if you want to send an updated project file to your deployed project. Sending a gem or configuration file to an arbitrary directory on the server is not as easy. It is hard to break out of its project-sized box.

Our strategy so far has been to try and minimize our interaction with servers that were more than one hop away from our laptops. When we did have to restart a daemon or look at log files, we would have to do the SSH hop, hop, hop ritual and do our thing. Then exit, exit, exit until we’re back on our laptop’s bash shell. Having RSA key logins to a number of servers saves the trouble of having to enter passwords, but the manual SSH-hopping does get tedious after a while.

Being the kind of programmer who rather scripts the tedious things away rather than perfecting his typing speed to speed up repetitive tasks, I figured it must be possible to automate these things. Knowing I’m not the only one with this problem, Google led me to a solution. Net-ssh-gateway (NSG). Thank you, Jamis Buck!

NSG makes it possible to establish an SSH connection through a gateway server to the next gateway server behind it using port forwarding. Repeat this multiple times until you’ve connected to the final server. The code for this looks like this:

Since this is rather bulky and non-DRY code, let’s condense it into something that involves less repeating of code:

Capistrano uses NSG internally for its gateway connection code, but it seems kinda tightly coupled with Capistrano internals. Also, when I looked at it for the first time, I did not really get how it worked or what it did. To gain a better understanding, I decided to extract the relevant code into a script and rework it to be stand-alone.

The great thing about trying to do something with code you don’t really understand is that you will understand it once you have dissected it far enough. After that, you can work with it and adapt it to suit your needs.

This resulted in an early version of SimpleGate, my attempt at creating a wrapper library around NSG to make gateway chaining easier. The first version was simply the relevant Capistrano method reworked to work in isolation. The next version improved on the gateway chaining by making at as easy as calling SimpleGate.new.through_to(%w[foo bar baz]) to connect through foo and bar to baz.

SimpleGate also has a ServerDefinition to wrap a simple YAML configuration file that stores the actual server connection information. This is useful for cronjob-activated scripts and other non-interactive code when you have a password authentication server in the chain of gateways. For command line tools using SimpleGate, it saves typing.

Capistrano has a good support for SSH, its configuration files and the various authentication schemes. Passwords and RSA keys are both not a problem. SimpleGate currently only supports passwords, as that is what NSG supports out of the box. RSA key logins are a todo item. For configuration, it does the simplest thing that can possibly work: just store the connection info as a plain YAML file in ~/.servers.yml.

After two minor version bumps, I had something that was good enough to build a script that connected through multiple gateway servers to my target and request its uptime. The next step was to execute arbitrary commands, which was a small modification.

Here I discovered another hard to reproduce feature that Capistrano executes in a really nice way: sudo passwords. For some reason I still have to discover, SimpleGate does not let me enter a password when asked for it on the remote server: it just fails the password check and quits. I guess that is another todo item.

After discovering this I wanted to check up on another server that was hidden behind a number of hops and started to change the hard-coded gateway connection sequence in my test script to connect to the new server.

Woah! Wait! Full stop.

Hard-coded connection info is not good. The server name should be a command line option and the connection sequence should be figured out by the script, not by me. Since I was not interested in manually working out all possible connection sequences, I figured it was time to add a simple path-finding Router class to the project…

After a quick read of relevant sections in Bratko, to refresh my knowledge of the topic, I decided to model the search space as a directed non-cyclical graph and search through it using a simple depth-first recursive search algorithm. Support for cyclical graphs will be another todo.

For every node in the network, all its possible connections are described in a YAML file, that is just a Hash of Arrays with server name strings. A special ‘local’ node represents my laptop or any arbitrary internet-connected system. The search algorithm comes down to:

  1. If we search from target to target, return that the route is target.
  2. If the current node has outgoing connection possibilities, try them all, keep the shortest and return it with the current node prepended to the returned list of nodes.
  3. If there are no outgoing nodes, return nil.

This results in a relatively naive path finder, but with only 15 nodes in my network, this is not much of a problem. Smarter algorithms can be added once I actually need them.

A version bump later I remembered by original goal: upload a gem, install it and restart the daemon associated with it. Restarting is all done in userland, so that is not a problem. Installation requires sudo, which is still a todo item. Uploading was still open.

NSG can open a normal net/ssh session. net/sftp can use this session to do file transfers. A quick copy-paste-adjust later I had a new executable for copying a single file to a single server, through an arbitrary number of hops.

Right now SimpleGate is at version 0.5.0 and it has the three items noted above as left to do. Then it has its core functionality and should be polished up for its 1.0 version.

The command line tools should get parameter support and a –help interface. Then the config files should both be documented and command-line editable. Once those things are in, multi-server support might be useful. In a Capistrano-like fashion connect to multiple servers (sequentially or in parallel) and execute commands on all of them or upload file(s) to them. The file uploader can get a better interface instead of mimicking the code.

Result of ACK: Future

Wikipedia’s definition of a Future in programming:

In computer science, futures and promises are closely related constructs used for synchronization in some concurrent programming languages. They both refer to an object that acts as a proxy for a result that is initially not known, usually because the computation of its value has not yet completed.

Yesterday evening a number of Rubyists from Amsterdam came together in the public library with our laptops to do cool computer stuff until the library closed.

Among the topics we discussed were new-ish programming languages such Ioke and Clojure. From here the discussion went to the languages that preceded them, like Self and IO.

I think that at some point someone asked “What can IO do that Ruby can’t do?”, so we started looking at the list of features of IO. There we discovered futures.

Futures look nifty: create an object that does not yet have a value and then move on and eventually do something with the object when you need its value. It will block if there is no value yet, which makes sense, but as long as you don’t need the value, you can just move on with your business. This can be useful to do heavy computations or to initiate asynchronous interaction with a remote API. As long as you don’t need the result immediately, a future can be useful.

Then I mentioned Ruby’s Thread#value, which was new to people. So a bit of code was created that looked similar to:

# sleeps for 3 seconds, then prints 615
t = Thread.new { sleep 3; 123}
puts t.value * 5

Explicitly creating a Thread and calling its value does the trick, but it is not very elegant. If you read it, you will probably end think, “What is that Thread doing? Oh, there’s a #value call there. Thread + #value is a future!”. Or you don’t make the connection and misunderstand what this code is doing.

How should it look then to be more elegant?

# sleeps for 3 seconds, then prints 615
f = future { sleep 3; 123}
puts f * 5

So, this is way more elegant! You see it is a future, because it says so! If you don’t know about futures, there is Wikipedia or Google and you might figure out what it does.

In order to make this happen, we need to define a future method that returns an object that when called returns Thread#value for that future. A proxy object. This leads to the next implementation:

class Proxy
 def initialize(&block)
   @thread = Thread.new(&block)
 end

 def method_missing(*args, &block)
   @thread.value.send(*args, &block)
 end
end

def future(&block)
 Proxy.new(&block)
end

f = future { sleep 3; 123}
puts f * 5

We created a Proxy class to do the threading logic and use method_missing to capture method calls, which we re-direct to Thread#value.

This works as long as you don’t call methods defined on Object or Kernel, because you get those for free in every class. You need to either avoid using them or get rid of them. There is BlankSlate, but since we were just trying to make our idea work, we just un-defined most methods on the object. Then we had the crazy idea to drop the Proxy object altogether and make Thread function as its own Proxy object. Thread, say bye-bye to your methods!

Here is the final bit of code we produced:

Then the library closed so we went home, after which I polished it a bit and created a github project for it.

This morning my colleague, Filip Slagter, asked me if there wasn’t already a library to do futures in Ruby. After a bit of searching, I found there is one. And it looks nice! Still, I like to re-invent the wheel. It is the best way to learn how something works.

Adventures in REIA land

One of my current interests is the new Reia programming language, created by Tony Arcieri. The wiki contains most of the documentation, but but besides a simple “Hello, World!” and Fibonacci implementation, there is not much working code. Reia is a work in progress, so that makes sense.

Philipp Pirozhkov created Ryan, a web framework built on top of Reia and YAWS. For reasons I have yet to figure out, it does not want to build on my machine. At least there’s more code to look at to learn the language. Ryan also has a RSpec-like syntax for writing tests, which look interesting.

Starting with web development might be a bit too ambitious for me. I actually managed to mess up a simple “Hello, world!” example, so I’m starting slow. Note to self: methods in Reia have parentheses. It’s not Ruby, where you can omit them.

Wrong hello world:

puts "Hello, world!"

Proper hello world:

puts("Hello, world!")

Sincy my brain still thinks in Ruby, let’s start with a simple bit of Ruby code and convert it to Reia.

First, the Ruby code:

[1,2,3].each { |n| puts n }

This prints out three lines with 1, 2 and 3 on them. Now the same code in Reia:

[1,2,3].each { |n| puts(n.to_s()) }

The two obvious differences:

  1. All method calls need their parentheses. So use “puts(‘String’)” instead of “puts ‘String’”.
  2. The int has to be explicitly cast to a String.

Just like Ruby, Reia has multiple ways to write this code. Another Ruby-esque way to write it is by using the ‘do’ block notation instead of curly braces:

[1,2,3].each do |n|
  puts(n.to_s())

Notice the puts() is indented and there is no “end”: that is the Python-style indentation at work. A third way to write the code is by (ab)using List Comprehensions:

[puts(x.to_s()) | x in [1,2,3]]

This is the strangest form for me, since Ruby does not have something similar. The way I interpret it is by reading from right to left: for each x in [1,2,3], do the puts thingy left of the pipe.

Hello, world!

After complaining over and over that I should really get myself a blog, I finally have one! Now, let’s be nice and let me introduce myself.

My name is Wes Oldenbeuving and I’m a programmer from Amsterdam, the Netherlands. My hobbies include reading books and blogs, playing video games, watching tv series and programming.

My interests cover a wide variety of topics like computer science, economic theory, history, (melodic) metal music, politics, philosophy, personal growth and cooking. I’m not a great chef, but I do try to improvise on recipes every once in a while.

I have been programming (in Ruby) since March 2006 for the Dutch company yoMedia. Ruby on Rails is what brought me to Ruby, but it is not the only thing keeping me. Ruby as a language is really nice to work with and works for both simple scripts, to automate mundane tasks, and to build complex applications. The people in the local Ruby communities are also nice, smart and full of crazy creative ideas.

We have a number of regular events that I attend 99% of the time: Amsterdam.rb, Utrecht.rb and the soon-to-start Amsterdam.rb screen-peeking diner thingy.

I expect my blog posts to mainly cover programming-related topics, though they will not necessarily be all about Ruby. In fact, expect the first posts to be about the new Reia programming language.