Customizing hosts file in Docker

In a project recently I had a need to add an entry to /etc/hosts and being new to Docker I was surprised to find that hosts is read only. Turns out this is a known issue, but I was able to find a work around. Essentially creating a copy of the library that handles hostname resolution and editing it to replace /etc/hosts with the path of a writable hosts file. Sounds daunting but it isn't all that scary, here's the step by step:

  1. Create a writable copy of /etc/hosts somewhere where the path will be the same length. I used /tmp/hosts:

    RUN cp /etc/hosts /tmp/hosts
    
  2. Then you need to make a copy of libnss_files.so that you can edit:

    RUN mkdir -p -- /lib-override && cp /lib/x86_64-linux-gnu/libnss_files.so.2 /lib-override
    
  3. Now edit the binary to replace /etc/hosts with the path to the writable hosts file (ex. /tmp/hosts):

    RUN perl -pi -e 's:/etc/hosts:/tmp/hosts:g' /lib-override/libnss_files.so.2
    
  4. Finish up by letting the system know where to find the edited binary:

    ENV LD_LIBRARY_PATH /lib-override
    

BuildBorg for Glass

I have been excited to write something for Glass ever since I received it and now I am proud to announce my first project. BuildBorg allows developers who wear Glass to receive notifications from their build server directly on their Glass. By adding BuildBorg as a web hook to your build server you will receive timeline cards for successful, failed, and fixed builds. From the BuildBorg settings you can enable/disable any of the notifications, that way if you only care about failed builds that will be the only timeline cards you will receive.

Right now BuildBorg supports CircleCI, Jenkins, Semaphore, TeamCity, and Travis CI. I am open to suggestions and hope to expand the service in the near future.

Google Glass and Windows 8.1

I recently received my Google Glass as a part of the Explorer Program. So what was the first thing I tried to do? Connect to it with adb of course. I was anxious to get started with the GDK but, as is commonly the issue, Windows 8.1 chose to not play nicely. Here are the steps I took to get my installation of Windows 8.1 Pro 64-bit edition to recognize my Google Glass.

  1. Locate the folder containing the Google USB Driver, it will be something similar to this:

    C:\<ADT install location>\sdk\extras\google\usb_driver\
    
  2. Edit the file named android_winusb.inf and add the following PID and VID for Google Glass to both the [Google.NTamd64] and [Google.NTx86] sections:

    ;Google Glass
    %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E11&REV_0216
    %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E11&MI_01
    
    
    %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_9001&REV_0216
    %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_9001&MI_01
    
  3. Disable Driver Signature Verification, excellent instructions can be found on How-To Geek.

  4. Open Device Manager and locate your Glass device. Right click the device and select Update Driver Software.

  5. Choose "Browse my computer for driver software".

  6. In the prompt labeled "Search for driver software on your computer:" enter the folder containing android_winusb.inf as found in step 1.

  7. A Windows Security dialog will pop up, choose "Install this driver software anyway".

After these steps you should have the drivers install properly. To verify run 'adb devices' and you should see your Glass listed. You can now use adb to sideload applications to you device. You can also use Droid@Screen to mirror the Glass display to your PC.

Google Glass for Rubyist

Disclaimer: I do not have access to the Google Glass Explorer Program. The code in this blog post is purely speculative, it is not production ready.

Google has recently made the developer documentation for it's Google Glass product publicly available. Named the Mirror API, it allows developers to create applications called Glassware that interacts with user's Glass devices via a RESTful interface. Developers authenticate to the API on the users behalf using OAuth v2. Once authorized, Glassware applications can publish timeline notifications to the user's Glass devices and subscribe to receive notifications of actions preformed on the devices.

Authorization

Since Glassware applications do not get installed directly onto Glass devices the first step to interacting with a user's device is the authorization process. This web based process has the user accessing your site and authenticating with their Google account by way of OAuth v2.

require 'google/api_client'
require 'sinatra'

CLIENT_ID = '<YOUR_CLIENT_ID>'
CLIENT_SECRET = '<YOUR_CLIENT_SECRET>'
SCOPES = [
  'https://www.googleapis.com/auth/glass.timeline',
  'https://www.googleapis.com/auth/userinfo.profile',
  # Add other requested scopes.
]

enable :sessions

def api_client; settings.api_client; end
def mirror_api; settings.mirror_api; end   
def oauth2_api; settings.oauth2_api; end

def store_credentials(user_id, credentials)
  raise NotImplementedError, 'store_credentials not implemented'
end

def get_stored_credentials(user_id)
  raise NotImplementedError, 'get_stored_credentials not implemented'
end

def get_user_info
  result = api_client.execute!(api_method: oauth2_api.userinfo.get,
                               authorization: user_credentials)
  user_info = nil
  if result.status == 200
    user_info = result.data
  else
    puts "An error occurred: #{result.data['error']['message']}"
  end
  user_info
end

def bootstrap_user
  # TODO: Welcome the user to your Glassware
end

def user_credentials
  @authorization ||= (
    auth = api_client.authorization.dup
    auth.redirect_uri = to('/oauth2callback')
    auth.update_token!(
      get_stored_credentials(session[:user_id])
    )
    auth
  )
end

configure do
  client = Google::APIClient.new
  client.authorization.client_id = CLIENT_ID
  client.authorization.client_secret = CLIENT_SECRET
  client.authorization.scope = SCOPES

  mirror = client.discovered_api('mirror', 'v1')
  oauth2 = client.discovered_api('oauth2', 'v2')

  set :api_client, client
  set :mirror_api, mirror
  set :oauth2_api, oauth2
end

before do
  unless user_credentials.access_token || request.path_info =~ /^\/oauth2/
    redirect to('/oauth2authorize')
  end
end

get '/oauth2authorize' do
  redirect user_credentials.authorization_uri.to_s, 303
end

get '/oauth2callback' do
  user_credentials.code = params[:code] if params[:code]
  user_credentials.fetch_access_token!

  user_info = get_user_info
  session[:user_id] = user_info.id
  store_credentials user_info.id, user_credentials
  bootstrap_user

  redirect to('/')
end

get '/' do
  "<h1>Welcome to my Glassware</h1>"
end

The above Sinatra application authenticates the user and stores their authentication for later use. Storing the user's authentication isn't required but it could prove important as most of the time you will be pushing timeline updates to a user's device when they are away from their computer.

Timeline Cards

Timeline cards allow developers to present information to their users. As timeline cards are added through the API they are presented as a queue the that the user can read through as they wish. You may have notice the # TODO comment in the above example, lets use that method to push a timeline card that welcomes the user to our Glassware application.

def insert_timeline_item(timeline_item, opts)
  if opts[:filename]
    media = Google::APIClient::UploadIO.new(opts[:filename], opts[:content_type])
    result = api_client.execute(
      api_method: mirror_api.timeline.insert,
      body_object: timeline_item,
      media: media,
      parameters: {
        'uploadType' => 'multipart',
        'alt' => 'json'}
      authorization: user_credentials)
  else
    result = api_client.execute(
      api_method: mirror_api.timeline.insert,
      body_object: timeline_item,
      authorization: user_credentials)
  end
  if result.success?
    result.data
  else
    puts "An error occurred: #{result.data['error']['message']}"
  end
end

def bootstrap_user
  text = "Welcome to JasonInCode's Mirror API for Rubyist"
  timeline_item = mirror_api.timeline.insert.request_schema.new({ 'text' => text })
  insert_timeline_item(timeline_item)
end

Now when a user authenticates to the application they receive a timeline card welcoming them. You may have noticed that the insert_timeline_item method has a set of optional parameters. This implementation of insert_timeline_item allows the developer to upload images and other media to a user's timeline.

get '/send_image' do
  text = "Sample image upload"
  timeline_item = mirror_api.timeline.insert.request_schema.new({ 'text' => text })
  insert_timeline_item(
    timeline_item,
    {
      filename: 'sample.png',
      content_type: 'image/png'
    }
  )
end

In addition to adding images, audio, and video a developer can also upload a list of actions the user can perform on a timeline card. There are a number of system provided menu items built into Glass devices:

  • REPLY and REPLY_ALL: Initiates a reply to the timeline item using the voice recording UI.
  • DELETE: Deletes the timeline item.
  • SHARE: Allows the Glass user to share the timeline item with their contacts.
  • READ_ALOUD: Tells the device to read the item's speakableText to the user, if that is not set it will read the item's text instead.
  • VOICE_CALL: Calls the phone number in the item's creator.phone_number.
  • NAVIGATE: Starts navigation to the item's location.
  • TOGGLED_PINNED: Toggles the item's isPinned state.

Developers can also provide custom menu items that are specific to the individual Glassware application. The custom menu items can have custom display text and an icon image. Each custom menu item has an id that is returned to the application via the application's registered subscription URL.

get '/item-with-actions' do
  text = "How much wood could a woodchuck chuck?"
  speakableText = "If a woodchuck could chuck wood."
  timeline_item = mirror_api.timeline.insert.request_schema.new({
    'text' => text, 'speakableText' => speakableText
  })

  menuItems = []

  menuItems << { 'action' => 'READ_ALOUD' }

  menuItems << {
    'action' => 'CUSTOM',
    'id' => 'id-for-notification',
    'values' => [{
      'displayName' => 'JasonInCode Action',
      'iconUrl' => 'path/to/icon.png'
    }]
  }

  timeline_item.menuItems = menuItems
  insert_timeline_item(timeline_item)
end

Subscriptions

As mentioned above a Glassware application can register to receive a notifications from a user's Glass device. When creating a subscription the developer specifies a URL for Google to send a request to about the user's actions.

def subscribe_to_notification(collection, callback_url)
  subscription = mirror_api.subscriptions.insert.request_schema.new({
    'collection' => collection,
    'userToken' => session[:user_id],
    'callbackUrl' => callback_url
  })

  result = api_client.execute(
    api_method: mirror_api.subscription.insert,
    body_object: subscription,
    authorization: user_credentials)

  if result.success?
    result.data
  else
    puts "An error occurred: #{result.data['error']['message']}"
  end
end

def bootstrap_user
  # ...

  subscribe_to_notification('timeline', to('/notify'))
end

The code above tells Google to let your application know when a user does an UPDATE, INSERT, or DELETE on their timeline. Google will send a POST request to the specified callbackUrl containing a minimal JSON ping that contains the information to retrieve the full information about. It is important to note that Google requires that the callbackUrl be secured via HTTPS.

post '/notify' do
  request = JSON.parse(request.body.read)

  session[:user_id] = request['userToken']

  text = "Got a notification: #{request}"
  timeline_item = mirror_api.timeline.insert.request_schema.new({ 'text' => text })
  insert_timeline_item(timeline_item)
end

I hope by now you can see the possiblities that Ruby and the Mirror API make available to developers. There are stil topics I didn't touch on such as the Contacts and Location APIs, perhaps in a future post.

Ruby, the Missing LINQ Blues

Having spent a lot of time in the realm of .NET I grew accustomed to LINQ or Language Integrated Queries. LINQ is a way to query
collections of objects in a SQL-like DSL. While there is not a direct competitor to the DSL provided by LINQ in Ruby there are
several methods that are equivalent to the extension methods provided by LINQ that exist in Ruby.

Where()

One of the most used (just guessing) LINQ methods would be Where(), in .NET allows you to provide a Lambda that is used to
filter a collection of objects.

var ints = new[] { 13, 42, 96, 2, 83 };

var evens = ints
    .Where(x => x % 2 == 0);

foreach (int i in evens)
{
  Console.WriteLine(i);
}

And in Ruby this functionality would be achieved with select.

ints = [ 13, 42, 96, 2, 83 ]

evens = ints
    .select { |x| x % 2 == 0 }

puts evens

Both examples output 42, 96, and 2. In the Ruby example find_all would be interchangeable with select.

Select()

In .NET to map a set of items to a different set of items one would use the Select() method. This method
is also useful for creating projections of a collection.

var words = new[] { "Hello", "JasonInCode", "Readers" };

var shouting = words
    .Select(x => x.ToUpper();

foreach (String s in shouting)
{
  Console.WriteLine(s);
}

In Ruby you have two options again map and collect. Both are used in the same manner, supply a block that receives
a single parameter that is an individual item in the collection and returns the object that it is to be mapped to.

words = %w{ Hello JasonInCode Readers }

shouting = words
    .map { |x| x.upcase }

puts shouting

Both the .NET and Ruby examples will output "HELLO JASONINCODE READERS".

Count()

In .NET you can call the Count() method with no arguments to count the entire collection or provide a Lambda to filter which
items get counted. It's usage in .NET looks as follows:

var ints = new[] { 13, 42, 96, 2, 83 };

var all = ints
    .Count();

var some = ints
    .Count(x => x >= 42);

var one = ints
    .Count(x => x == 42);

Console.WriteLine(all);
Console.WriteLine(some);
Console.WriteLine(one);

That would output 5, 3, and 1. To do the similar task in Ruby one would use the count method as so:

ints = [ 13, 42, 96, 2, 83 ]

all = ints
    .count

some = ints
     .count { |x| x >= 42 }

one = ints
    .count 42

puts all, some, one

Any()

Any() is useful when you need to determine if a collection contains one or more items that pass a provided test.

var words = new[] { "C#", "Ruby", "VisualBasic", "Java" };

var yes = words
    .Any(x => x.Contains("y"));

var no = words
    .Any(x => x.Contains("x"));

Console.WriteLine(yes);
Console.WriteLine(no);

Ruby collections have the any? method that serves the very same purpose.

words = %w{ C# Ruby VisualBasic Java }

yes = words
    .any? { |x| x.include? "y" }

no = words
    .any? { |x| x.include? "x" }

puts yes, no

Both example will output true followed by false.

When switching from .NET to Ruby it is nice to find some of my old creature comforts came along for the
ride. And once I started learning more about Ruby not only did I find the niceties listed above but a whole
list of methods that make Ruby an enjoyable programming experience.

Bonus

If you have spent time in .NET then you likely come across extension methods. A lot of LINQ's methods are actually
implemented as extension methods. Extension methods are .NET's way of adding methods to a class that is already
implemented.

public statis class StringExtension
{
  public static bool Palindrome(this String me)
  {
    var arr = me.ToLower.ToCharArray();
    Array.Reverse(arr);
    return me.ToLower == new String(arr);
  }
}

Ruby, having an open class implementation, has a much better approach then extension methods. Since a class is never
final a developer is free to add and redefine methods.

class String
  def palindrome?
    self.downcase == self.downcase.reverse
  end
end