Recently by John Cato

A common CSS problem is the need to crop and scale an image on a page. Scaling an image is easily done using the hight and width attributes of the image. Likewise cropping an image can be accomplished by using the image as a background of an element and setting the hight and width of the element. Both scaling and cropping an image is a bit more involved however, and if it's something that's done often it pays to have a class that handles the creation of cropped and scaled images. For this purpose I've written the Croppenscaler.

The idea here is to create a div element with a set size that has a nested div within that displays a relatively positioned image. I found that it was useful to have a hash of image data that defines the default size and crop position of an image. These values are adjusted when the frame is built so that no matter what scale the resulting frame has, the image is positioned in the same place.

CSS Classes

Let's examine the nessessary CSS classes first:


  .croppenscaler {
    display: inline-block;
    overflow: hidden;
  }

  .croppenscaler img {
    position: relative;
    border: none;
  }

The important attributes to note above are the use of overflow on the main croppenscaler, this ensures that the top frame has the intended size. The nested image is positioned relatively. All of the other CSS attributes are written in the style attribute because they have to be calculated when the frame is built.

The Croppenscaler Class:

The javascript below uses the Prototype framework, but it could just as easily use JQuery or raw javascript to accomplish the same thing.


var imageData = {
  kittah: {  width:900, top:-175, left:-165, url: 'http://www.nearinfinity.com/blogs/assets/jcato/images/Kittah.jpg' },
};

var Croppenscaler = Class.create();
Croppenscaler.prototype = {

  initialize: function(options) {
    var image = imageData[options.image];

    this.url = image.url;
    this.frameHeight = options.height || 400;
    this.frameWidth = options.width || 300;

    var scale = this.frameWidth / 300;

    this.imageWidth = (image.width) * scale;
    this.positionTop = (image.top) * scale;
    this.positionLeft = (image.left) * scale;
  },

  buildFrame: function() {

    var img = new Element('img',{src:this.url, 'class':'zoom'});
    img.setStyle({
      width: this.imageWidth+'px',
      top: this.positionTop+'px',
      left: this.positionLeft+'px',
    });

    var frame = new Element('div',{'class':'croppenscaler'});
    frame.update(img);
    frame.setStyle({
      height:this.frameHeight+'px',
      width:this.frameWidth+'px',
    });

    return frame;
  },
};

The class has two functions. The constructor takes a hash of options for the resulting frame; the image key and the height and width of the frame. In this version the constructor references an imageData hash to get the details about the image to display, but they could be passed into the function as well. The important thing is that the constructor has access to the height and width of the frame, as well as the default width of the image and the top and left attributes that define where the upper left corner of the image should be when it's displayed at its default width.

The buildFrame() function takes the calculated sizes and uses them to construct the frame div, with a nested image at a scale that fits within the frame, and positioned the same at any scale.

Then to use the class, create a new Croppenscaler with a hash that at least includes the image key, and an optional height and width, call the buildFrame() function and insert the resulting element onto the page.

var loadImages = function() {
  $('cats').insert(new Croppenscaler({image:'kittah'}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',height:300}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:400,height:250}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:200,height:300}).buildFrame());
  $('cats').insert(new Croppenscaler({image:'kittah',width:100,height:150}).buildFrame());
}

The above code will then produce the clowder of cats below.

Capistrano is great to work with. It's simple, powerful and flexible. For the last couple of weeks I've been building a series of Capistrano tasks that check the status and configuration of our web servers. I'm pretty happy with the results, so I though I would share the basic structure of what I've come up with. I'm just going to provide a couple of tasks here, along with all of the support methods, to provide a framework, but the idea would be to expand it with whatever commands would be run to verify the health of a server.

There were several requirements that I had to keep in mind when I was designing this

  1. The cap tasks should use the environment configuration files that we already have.
  2. Because there are a large number of tasks we should be able to run them individually, or with a single command we should be able to run the entire suite.
  3. The cap script should produce well formatted, easy to read output, so that it's clear what's broken and where.


Control Support Methods

While building the validation tasks I found that I was having to do the same basic operations fairly often:

  1. Issue a command on a remote host.
  2. Parse the output of that command.
  3. Issue more commands based on the output.

Or sometimes I just wanted to run a series of commands on one host, verifying that it was correct before moving on to the next. It's possible to make Capistrano work this way, but it's not well documented. By default, if you give Capistrano multiple commands to run on multiple hosts, the it will run the commands in host order. However what I really wanted is for Capistrano to run the commands in command order.

For instance: given that we have host-A, host-B, host-C, and I want to run commands doA, doB, and doC by default Capistrano will run:

    HostA > doA
    HostB > doA
    HostC > doA
    HostA > doB
    HostB > doB
    HostC > doB
    HostA > doC
    HostB > doC
    HostC > doC

But what I needed it to do was:

    HostA > doA
    HostA > doB
    HostA > doC
    HostB > doA
    HostB > doB
    HostB > doC
    HostC > doA
    HostC > doB
    HostC > doC

By using the roles that we already have configured for our deploy tasks with Capistrano we were able to create a few support methods that issue commands in the order that we want.


each_host

The each_host method is used to iterate through our configured hosts. The method prints out the hostname (which is important for the look of the script's output) sets the current host, then yields the block that was passed into it.

  def each_host
    roles[:web].each do |host|
      print_hostname host
      set(:current_host, host.host)
      yield host
    end
  end


run_serial

The run_serial method runs the given command, but only on the current host, yielding the output of the command and the name of the output stream (:out or :err). The ssh channel we don't have much use for.

  def run_serial(command)
    run command, :hosts => fetch(:current_host) do |chan, stream, data|
      yield stream, data
    end
  end


run_primary

We also have a primary server set in our configuration. We can create a few more support methods that take advantage of the primary host, for issuing command on one host only.

  def run_primary(command)
    run command, :hosts => fetch(:primary) do |chan, stream, data|
      set_current_host channel
      yield stream, data
    end
  end


currently_primary?

Having a method that tells us if we're currently on the primary host is helpful as well.

  def currently_primary?
    fetch(:current_host) == fetch(:primary).host
  end


set_current_host

The current host can also be set from the ssh channel. This method is called from the run_primary method, but this needs to be called when we call the default run method.

  def set_current_host(channel)
    host = channel.properties[:host]
    print_hostname host
    set(:current_host, host)
  end

Now we can write tasks that execute in in command order, execute tasks just on the primary host, and as we're preforming checks we print out the current host, so we're able to keep track of where we are.



Printing Support Methods

Because printing the script output out to the command line is an important part of the script I'm going to go over the printing support next. When running the server checks I wanted the output to look like rspec or cucumber. As each check is performed I wanted to see a colorful pass or fail message with the values that I was checking against to be highlighted. Also once the checks were finished I wanted to see a list of everything that failed, grouped by host.


print_hostname

This is the print_hostname method that was mentioned above. Everytime we move to a different host this method prints out the hostname.

  def print_hostname(name)
    puts "    Host: #{grey(name)} >"
  end


step

Also at the beginning of every task I wanted to print the task name and the number of the task.

  def step(name)
    step = fetch(:step)
    puts "\n[#{step}] #{name}"
    set(:step, step+1)
  end


failure

The failure method is called when a check fails. It prints the failure message, and stores it under the current hostname so that it can be printed again after all the checks have been done. If the expected or actual parameters are included it prints those along with the message, otherwise just the message is printed.

  def failure(message, expected=nil, actual=nil)
    host = fetch(:current_host)
    complete = (expected || actual) ?
      "#{message} Expected: #{grey(expected)} Actual: #{grey(actual)}" :
      message
    errors = fetch(:errors)
    unless errors[host]
      errors[host] = []
    end
    errors[host] << message
    log_item(complete, :fail)
  end


pass

The pass method is called when a check passes.

  def pass(message)
    log_item(message, :pass)
  end


log_item

The log_item method is called by the pass and failure methods. The method includes a warn and empty status which can also be used by the tasks when printing their status.

  def log_item(message, flag=nil)
    status = case flag
      when :pass : "      [#{green("PASS")}] "
      when :fail : "      [#{red("FAIL")}] "
      when :warn : "      [#{orange("WARN")}] "
      else "      "
    end
    puts "#{status}#{message}"
  end


colorize

The methods below handle the coloring of the text as it's printed to the command line. This was actually pretty fun figuring out. Every script should have fancy colorized output. (and now every script of mine will, muaha ha ha)

  def red(text)
    colorize(text, 31)
  end

  def orange(text)
    colorize(text, 33)
  end

  def green(text)
    colorize(text, 32)
  end

  def grey(text)
    colorize(text, 37)
  end

  def colorize(text, color_code)
    "\e[#{color_code}m#{text}\e[0m"
  end


Start and Finish Tasks

Now that all that's taken care of we can start writing some actual Capistrano tasks to take advantage of our fine grained control and fancy printing.


These server check tasks all share common startup and finish tasks that need to be run before and after any one of the tasks are run, or when the entire suite is run. This is defined using Capistrano's :start and :finish callbacks, but should only be run for the check tasks.
  TASK_LIST = [
    "check:all",
    "check:environment_variables",
    "check:middleware_versions",
    "check:apache_configuration"]

  on :start, 'check:setup', :only => TASK_LIST
  on :finish, 'check:print_errors', :only => TASK_LIST

setup

The setup task handles whatever specific setup needs to be done, but at the very least the step and errors variables need to be defined. They're used by the printing methods. Also, all of the tasks below are inside of the check namespace.

  namespace :check do

    task :setup do
      set :step, 1
      set :errors, {}
    end


print_errors

The print errors method is run after all the checks have been run to print a convenient list of errors grouped by host. This keeps errors from being lost in the output.

  task :print_errors do
    errors = fetch(:errors)
    if (errors.size() > 0)
      print "\n ==== #{red 'Errors'} ===="
      errors.each do |host,list|
        print_hostname host
        list.each {|e| puts "      #{e}"}
      end
    end
  end


Validation Tasks

The meat of the script are in the validation tasks. Out current script has fifteen different tasks that do everything from checking environment variables, to verifying directory and file permissions, to checking network and database statuses. If it can be automated, we'll find a way to get it in. Rather then include concrete examples though I'm just going to include some skeleton methods to show the method structure to illustrate how the support methods are used together in the Capistrano tasks.


Simple Tasks

This task executes one command on each server and validates the output from a list of expected results. This form is used by our script to check environment variables, commands on the sudo list, and programs in the cron, all of which can be read and verified with one command. I'm just including the validateVariable, and getVariable methods here to show the pass and failure methods.

  VARIABLES = [
    { :key => 'KEY', :value => /Expected Value/ },
    { :key => 'KEY', :value => /Expected Value/ },
    { :key => 'KEY', :value => /Expected Value/ }]

  task :simple do
    step "A Simple Check"
    run "env" do |channel, stream, data|
      set_current_host channel
      VARIABLES.each do |map|
        validateVariable(data, map)
      end
    end
  end

  def validateVariable(data, map)
    value = getVariable(data, map[:key])
    (value.match map[:value]) ?
      pass("Env #{grey(map[:key])} is set to #{grey(value)}") :
      failure("Env #{grey(map[:key])} is incorrect", map[:value].inspect, value)
  end

  def getVariable(data, key)
    result = data.match /^#{key}=(.*)/
    unless result
      failure "Env #{grey(key)} is not set."
      return nil
    end
    result[1]
  end


Tasks that run multiple commands on the same host

Most of the tasks in our validation script run multiple commands on the same host, using the each_host and run_serial methods. This allows us to read files and act on the values in those files. It's alse used because the script output looks better organized when running tasks in host order. The task below itterates through a list of standard directories, then a list of configured directories. For each directory a run_serial command is executed to see if the directory exists, then once the lists have been gone through it's done again on the next host.

  task :serial_example do
    step "Run multiple commands on a host"
    each_host do
      DIRECTORIES.each do |dir|
        verify_directory dir
      end

      [:deploy_to, :transfer_path, :cache_path].each do |key|
        dir = fetch(key)
        if (dir)
          verify_directory dir
        else
          falure "No directory configured for #{grey(key)}"
        end
      end

    end
  end

  def verify_directory(path)
    command = "[ -d #{path}] && echo 'true' || echo 'false'"
    run_serial command do |stream, data|
      if (data.strip == 'true')
        pass "Verified that #{grey(path)} exists."
      else
        failure "Directory at #{grey(path)} does not exist."
      end
    end
  end


Tasks using different server combinations

Here's a command that runs on the primary host, reads a file, then acts across multiple hosts. We do something like this to verify that the Apache configuration is correct. We know the httpd.conf is the same across hosts, but we want to verify that the files and directories that are in the configuration are actually on the host in question.

  task :primary_example do
    step "Verifying Certificates"
    path = fetch(:path_to_httpd_conf)
      certs = {}
      run_primary "grep SSLC[eA] #{path}" do |stream,data|

        if (stream == :err)
          failure "No http configuration file at #{grey(path)}"
          break
        end

        keys = [
          'SSLCertificateFile',
          'SSLCertificateKeyFile',
          'SSLCACertificatePath',
          'SSLCARevocationPath']

        keys.each do |key|
          certs[key] = read_http_conf_value(data,key)
        end

        pass "Read Certificate Paths from HTTP Configuration"
      end

      each_host do
        verify_file certs['SSLCertificateFile']
        verify_file certs['SSLCertificateKeyFile']
        verify_directory certs['SSLCACertificatePath']
        verify_directory certs['SSLCARevocationPath']
      end
    end


And finally we need a task that runs the whole suite of validation tasks. The all task does nothing itself, it just runs all of the other tasks.

  desc "Run all of the validation tasks"
  after "check:all",
    "check:environment_variables",
    "check:middleware_versions",
    "check:apache_configuration"

  task :all do
  end

Then to execute the cap task you would type is:

cap -q production check:all

And watch as all the beautiful passes and fails scroll by, though hopefully more of the former.

Like Javascript, semicolons are optional in Groovy except for when they aren't optional. These examples are both pretty contrived, though I found both because they're actually something that I've written, and could both be written better. That's not really the point I'm making though. When something doesn't compile when it looks like it clearly should sometimes it's hard to track down why, and it's surprising to learn that it's because you need a semicolon.

Example the first: Generics at the end of a line:

def list = [1,2,3] as List<Integer>
println list

If you try to compile this in Groovy it will give you the error message: 'unexpected token: println', however this:

def list = [1,2,3] as List<Integer>;
println list
Gives the expected output.


Example the second: Ambiguous Closures

{-> assert GroovyClosureTest == owner.getClass() }()
{-> assert GroovyClosureTest == delegate.getClass() }()

I don't think you'd really ever need to do something like this, but a closure can be defined and called on a single line. Because of Groovy's special closure parameter syntax (e.g. list.each() {} being synonomous with list.each({})) the compiler thinks I'm passing the second closure into the first as an argument. Again a semicolon is needed to seperate the two lines:

{-> assert GroovyClosureTest == owner.getClass() }();
{-> assert GroovyClosureTest == delegate.getClass() }()

I've been interested in data visualization for a long time now, probably because I have backgrounds in both programming and art. After a quick look at the kind of output that the language Processing can create, I think that it's got to go on my lengthening to do list.

I hate blogs that are just links to other blogs, but here's an article about character encodings that everyone should take a look at if you don't have a good understanding of how they work.

http://www.joelonsoftware.com/articles/Unicode.html