On 30/11/10 17:12 -0500, [email protected] wrote:

Hi,

</snip>
!! Unexpected error while processing request: undefined method `match' for
nil:NilClass
undefined method `match' for nil:NilClass
  ././lib/sinatra/rack_driver_select.rb:18:in `extract_driver'
    ././lib/sinatra/rack_driver_select.rb:10:in `call'
</snip>

There should be an easy fix, just check if header is set or not.
Otherwise, this patch looks good to me, ACK after this issue will be fixed.

  -- Michal


From: Tobias Crawley <[email protected]>

---
server/lib/drivers.rb                      |   97 +++++++++++++++-------------
server/lib/sinatra/lazy_auth.rb            |    2 +-
server/lib/sinatra/rabbit.rb               |    8 +-
server/lib/sinatra/rack_driver_select.rb   |   22 ++++++
server/server.rb                           |   41 ++++++++----
server/views/api/drivers.xml.haml          |    6 ++
server/views/api/show.html.haml            |    4 +-
server/views/api/show.xml.haml             |    2 +-
server/views/errors/backend_error.xml.haml |    2 +-
server/views/layout.html.haml              |    2 +-
10 files changed, 117 insertions(+), 69 deletions(-)
create mode 100644 server/lib/sinatra/rack_driver_select.rb
create mode 100644 server/views/api/drivers.xml.haml

diff --git a/server/lib/drivers.rb b/server/lib/drivers.rb
index 6e31bb7..43c5bea 100644
--- a/server/lib/drivers.rb
+++ b/server/lib/drivers.rb
@@ -1,51 +1,60 @@
-DRIVERS = {
-  :ec2 => { :name => "EC2" },
-  :rackspace => { :name => "Rackspace" },
-  :gogrid => { :name => "Gogrid" },
-  :rhevm => { :name => "RHEVM" },
-  :rimuhosting => { :name => "RimuHosting"},
-  :opennebula => { :name => "Opennebula", :class => "OpennebulaDriver" },
-  :terremark => { :name => "Terremark"},
-  :azure => { :name => "Azure" },
-  :mock => { :name => "Mock" }
-}
-
-DEFAULT_COLLECTIONS = [
-  :hardware_profiles,
-  :images,
-  :instances,
-  :instance_states,
-  :realms,
-  :storage_volumes,
-  :storage_snapshots
-]
-
-DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
-
-def driver_name
-  DRIVERS[DRIVER][:name]
-end
-
-def driver_class_name
-  basename = DRIVERS[DRIVER][:class] || "#{driver_name}Driver"
-  "Deltacloud::Drivers::#{driver_name}::#{basename}"
-end
+module Deltacloud
+  DRIVERS = {
+    :ec2 => { :name => "EC2" },
+    :rackspace => { :name => "Rackspace" },
+    :gogrid => { :name => "Gogrid" },
+    :rhevm => { :name => "RHEVM" },
+    :rimuhosting => { :name => "RimuHosting"},
+    :opennebula => { :name => "Opennebula", :class => "OpennebulaDriver" },
+    :terremark => { :name => "Terremark"},
+    :azure => { :name => "Azure" },
+    :mock => { :name => "Mock" }
+  }
+
+  DEFAULT_COLLECTIONS = [
+    :hardware_profiles,
+    :images,
+    :instances,
+    :instance_states,
+    :realms,
+    :storage_volumes,
+    :storage_snapshots
+  ]
+
+  DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
+
+  def driver_symbol
+    (Thread.current[:driver] || DRIVER).to_sym
+  end

-def driver_source_name
-  File.join("deltacloud", "drivers", "#{DRIVER}", "#{DRIVER}_driver.rb")
-end
+  def driver_name
+    DRIVERS[:"#{driver_symbol}"][:name]
+  end

-def driver_mock_source_name
-  return File.join('deltacloud', 'drivers', DRIVER.to_s, 
"#{DRIVER}_driver.rb") if driver_name.eql? 'Mock'
-end
+  def driver_class_name
+    basename = DRIVERS[:"#{driver_symbol}"][:class] || "#{driver_name}Driver"
+    "Deltacloud::Drivers::#{driver_name}::#{basename}"
+  end

-def driver
-  require driver_source_name
-  #require 'deltacloud/base_driver/mock_driver.rb'
+  def driver_source_name
+    File.join("deltacloud", "drivers", "#{driver_symbol}", 
"#{driver_symbol}_driver.rb")
+  end

-  if Sinatra::Application.environment.eql? :test
-    require driver_mock_source_name if driver_mock_source_name
+  def driver_mock_source_name
+    return File.join('deltacloud', 'drivers', "#{driver_symbol}",
+                     "#{driver_symbol}_driver.rb") if driver_name.eql? 'Mock'
  end

-  @driver ||= eval( driver_class_name ).new
+  def driver
+    require driver_source_name
+    #require 'deltacloud/base_driver/mock_driver.rb'
+
+    if Sinatra::Application.environment.eql? :test
+      require driver_mock_source_name if driver_mock_source_name
+    end
+
+    @driver ||= eval( driver_class_name ).new
+  end
end
+
+include Deltacloud
diff --git a/server/lib/sinatra/lazy_auth.rb b/server/lib/sinatra/lazy_auth.rb
index 2a26fdf..99c416a 100644
--- a/server/lib/sinatra/lazy_auth.rb
+++ b/server/lib/sinatra/lazy_auth.rb
@@ -40,7 +40,7 @@ module Sinatra
    end

    def authorize!
-      r = "#{driver}-deltacl...@#{hostname}"
+      r = "#{driver_symbol}-deltacl...@#{hostname}"
      response['WWW-Authenticate'] = %(Basic realm="#{r}")
      throw(:halt, [401, "Not authorized\n"])
    end
diff --git a/server/lib/sinatra/rabbit.rb b/server/lib/sinatra/rabbit.rb
index 94c74e3..05bd6c5 100644
--- a/server/lib/sinatra/rabbit.rb
+++ b/server/lib/sinatra/rabbit.rb
@@ -60,7 +60,7 @@ module Sinatra
      def control(&block)
        op = self
        @control = Proc.new do
-          op.check_capability(driver)
+          op.check_capability(Deltacloud::driver)
          op.validate(params)
          instance_eval(&block)
        end
@@ -133,7 +133,7 @@ module Sinatra
      end

      def generate_documentation
-        coll, oper, features = self, @operations, driver.features(name)
+        coll, oper, features = self, @operations, 
Deltacloud::driver.features(name)
        ::Sinatra::Application.get("/api/docs/#...@name}") do
          @collection, @operations, @features = coll, oper, features
          respond_to do |format|
@@ -206,9 +206,9 @@ module Sinatra
    # operation on this collection.
    def collection(name, &block)
      raise DuplicateCollectionException if collections[name]
-      return unless driver.has_collection?(name.to_sym)
+      return unless Deltacloud::driver.has_collection?(name.to_sym)
      collections[name] = Collection.new(name, &block)
-      collections[name].add_feature_params(driver.features(name))
+      collections[name].add_feature_params(Deltacloud::driver.features(name))
      collections[name].generate
    end

diff --git a/server/lib/sinatra/rack_driver_select.rb 
b/server/lib/sinatra/rack_driver_select.rb
new file mode 100644
index 0000000..24c36de
--- /dev/null
+++ b/server/lib/sinatra/rack_driver_select.rb
@@ -0,0 +1,22 @@
+class RackDriverSelect
+
+  def initialize(app, opts={})
+    @app = app
+    @opts = opts
+  end
+
+  def call(env)
+    original_driver = Thread.current[:driver]
+    new_driver = extract_driver(env)
+    Thread.current[:driver] = new_driver if new_driver
+    @app.call(env)
+  ensure
+    Thread.current[:driver] = original_driver
+  end
+
+  def extract_driver(env)
+    driver_name = 
env['HTTP_HEADERS'].match(/X\-Deltacloud\-Driver:(\w+)/i).to_a
+    return driver_name[1] if driver_name[1]
+  end
+
+end
diff --git a/server/server.rb b/server/server.rb
index d3f7d8a..076859d 100644
--- a/server/server.rb
+++ b/server/server.rb
@@ -10,6 +10,12 @@ require 'erb'
require 'haml'
require 'open3'
require 'lib/deltacloud/helpers/blob_stream'
+require 'sinatra/rack_driver_select'
+
+set :version, '0.1.0'
+
+
+use RackDriverSelect

configure do
  set :raise_errors => false
@@ -48,23 +54,28 @@ Sinatra::Application.register Sinatra::RespondTo
# Redirect to /api
get '/' do redirect url_for('/api'); end

+get '/api/drivers\/?' do
+  respond_to do |format|
+    format.xml { haml :"api/drivers" }
+  end
+end
+
get '/api\/?' do
-    @version = 0.1
-    if params[:force_auth]
-      return [401, 'Authentication failed'] unless 
driver.valid_credentials?(credentials)
-    end
-    respond_to do |format|
-        format.xml { haml :"api/show" }
-        format.json do
-          { :api => {
-            :version => @version,
-            :driver => DRIVER,
-            :links => entry_points.collect { |l| { :rel => l[0], :href => 
l[1]} }
-            }
-          }.to_json
-        end
-        format.html { haml :"api/show" }
+  if params[:force_auth]
+    return [401, 'Authentication failed'] unless 
driver.valid_credentials?(credentials)
+  end
+  respond_to do |format|
+    format.xml { haml :"api/show" }
+    format.json do
+      { :api => {
+          :version => settings.version,
+          :driver => driver_symbol,
+          :links => entry_points.collect { |l| { :rel => l[0], :href => l[1]} }
+        }
+      }.to_json
    end
+    format.html { haml :"api/show" }
+  end
end

# Rabbit DSL
diff --git a/server/views/api/drivers.xml.haml 
b/server/views/api/drivers.xml.haml
new file mode 100644
index 0000000..7beb9c8
--- /dev/null
+++ b/server/views/api/drivers.xml.haml
@@ -0,0 +1,6 @@
+%api{ :version => settings.version }
+  %drivers
+    - DRIVERS.each do |id, details|
+      %driver{ :id => id }
+        %name<
+          =details[:name]
diff --git a/server/views/api/show.html.haml b/server/views/api/show.html.haml
index 0077972..74ec175 100644
--- a/server/views/api/show.html.haml
+++ b/server/views/api/show.html.haml
@@ -1,5 +1,5 @@
%h1
-  API v...@version}
+  API v#{settings.version}

%ul
  - collections.keys.sort_by { |k| k.to_s }.each do |key|
@@ -12,4 +12,4 @@
            = op
  %li
    %strong
-      %a{:href => url_for("/api/docs")} Documentation (v...@version})
+      %a{:href => url_for("/api/docs")} Documentation (#{settings.version})
diff --git a/server/views/api/show.xml.haml b/server/views/api/show.xml.haml
index 70c26c9..f68fd79 100644
--- a/server/views/api/show.xml.haml
+++ b/server/views/api/show.xml.haml
@@ -1,4 +1,4 @@
-%api{ :version=>@version, :driver=>DRIVER }
+%api{ :version => settings.version, :driver => driver_symbol }
  - for entry_point in entry_points
    %link{ :rel=>entry_point[0], :href=>entry_point[1] }
      - for feature in driver.features(entry_point[0])
diff --git a/server/views/errors/backend_error.xml.haml 
b/server/views/errors/backend_error.xml.haml
index 75866eb..4aba8c0 100644
--- a/server/views/errors/backend_error.xml.haml
+++ b/server/views/errors/backend_error.xml.haml
@@ -1,6 +1,6 @@
%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
  %kind backend_error
-  %backend{ :driver => DRIVER }
+  %backend{ :driver => driver_symbol }
    %code= @error.code
    %cause= @error.cause
    - if @error.details
diff --git a/server/views/layout.html.haml b/server/views/layout.html.haml
index c46b15b..1556272 100644
--- a/server/views/layout.html.haml
+++ b/server/views/layout.html.haml
@@ -19,7 +19,7 @@
        = yield
      #footer
        #driver_info
-          Driver: #{DRIVER}
+          Driver: #{driver_symbol} | API version: #{settings.version}
        #copyright
          Copyright 2009, 2010
          %a{:href => 'http://redhat.com'} Red Hat
--
1.7.3.2


--
--------------------------------------------------------
Michal Fojtik, [email protected]
Deltacloud API: http://deltacloud.org
--------------------------------------------------------

Reply via email to