def authenticate(opts={}, &block)
      block ||= lambda do |params|
        config[:auth_credentials].each do |key, value|
          begin
            params[key] = value
          rescue NameError => e
            raise NameError.new("Unknown param name '#{key}'")
          end
        end
      end

      response = auth_service.request(config[:auth_service][:request].to_sym, opts, &block)

      if [200, 201].include? response.status
        @auth_response = Hashish.new({
          :headers => response.headers,
          :body    => response.body
        })
        update_services_session_data
      else
        raise AuthenticationError.new(response.body)
      end
      self
    end
def authenticate(opts={}, &block)
      block ||= lambda do |params|
        config[:auth_credentials].each do |key, value|
          begin
            params[key] = value
          rescue NameError => e
            raise NameError.new("Unknown param name '#{key}'")
          end
        end
      end

      response = auth_service.request(config[:auth_service][:request].to_sym, opts, &block)

      if [200, 201].include? response.status
        @auth_response = Hashish.new({
          :headers => response.headers,
          :body    => response.body
        })
        update_services_session_data
      else
        raise AuthenticationError.new(response.body)
      end
      self
    end
Create a new Session instance.

 <b>Initialize with a config file</b>

  Aviator::Session.new(:config_file => 'path/to/aviator.yml', :environment => :production)

 In the above example, the config file must have the following form:

  production:
    provider: openstack
    auth_service:
      name: identity
      host_uri: 'http://my.openstackenv.org:5000'
      request: create_token
      validator: list_tenants
      api_version: v2
    auth_credentials:
      username: myusername
      password: mypassword
      tenant_name: myproject

 <b>SIDENOTE:</b> For more information about the <tt>validator</tt> member, see Session#validate.

 Once the session has been instantiated, you may authenticate against the
 provider as follows:

  session.authenticate

 The members you put under <tt>auth_credentials</tt> will depend on the request
 class you declare under <tt>auth_service:request</tt> and what parameters it
 accepts. To know more about a request class and its parameters, you can use
 the CLI tool <tt>aviator describe</tt> or view the request definition file directly.

 If writing the <tt>auth_credentials</tt> in the config file is not acceptable,
 you may omit it and just supply the credentials at runtime. For example:

  session.authenticate do |params|
    params.username    = ARGV[0]
    params.password    = ARGV[1]
    params.tenant_name = ARGV[2]
  end

 See Session#authenticate for more info.

 Note that while the example config file above only has one environment (production),
 you can declare an arbitrary number of environments in your config file. Shifting
 between environments is as simple as changing the <tt>:environment</tt> to refer to that.


 <b>Initialize with an in-memory hash</b>

 You can create an in-memory hash with a structure similar to the config file but without
 the environment name. For example:

  configuration = {
    :provider => 'openstack',
    :auth_service => {
      :name      => 'identity',
      :host_uri  => 'http://devstack:5000/v2.0',
      :request   => 'create_token',
      :validator => 'list_tenants'
    }
  }

 Supply this to the initializer using the <tt>:config</tt> option. For example:

  Aviator::Session.new(:config => configuration)


 <b>Initialize with a session dump</b>

 You can create a new Session instance using a dump from another instance. For example:

  session_dump = session1.dump
  session2 = Aviator::Session.new(:session_dump => session_dump)

 However, Session.load is cleaner and recommended over this method.


 <b>Optionally supply a log file</b>

 In all forms above, you may optionally add a <tt>:log_file</tt> option to make
 Aviator write all HTTP calls to the given path. For example:

  Aviator::Session.new(:config_file => 'path/to/aviator.yml', :environment => :production, :log_file => 'path/to/log')


 Authenticates against the backend provider using the auth_service request class
 declared in the session's configuration. Please see Session.new for more information
 on declaring the request class to use for authentication.

 <b>Request params block</b>

 If the auth_service request class accepts parameters, you may supply that
 as a block and it will be directly passed to the request. For example:

  session = Aviator::Session.new(:config => config)
  session.authenticate do |params|
    params.username    = username
    params.password    = password
    params.tenant_name = project
  end

 If your configuration happens to have an <tt>auth_credentials</tt> in it, those
 will be overridden by this block.

 <b>Treat parameters as a hash</b>

 You can also treat the params struct like a hash with the attribute
 names as the keys. For example, we can rewrite the above as:

  session = Aviator::Session.new(:config => config)
  session.authenticate do |params|
    params[:username]    = username
    params[:password]    = password
    params[:tenant_name] = project
  end

 Keys can be symbols or strings.

 <b>Use a hash argument instead of a block</b>

 You may also provide request params as an argument instead of a block. This is
 especially useful if you want to mock Aviator as it's easier to specify ordinary
 argument expectations over blocks. Further rewriting the example above,
 we end up with:

  session = Aviator::Session.new(:config => config)
  session.authenticate :params => {
    :username    => username,
    :password    => password,
    :tenant_name => project
  }

 If both <tt>:params</tt> and a block are provided, the <tt>:params</tt>
 values will be used and the block ignored.

 <b>Success requirements</b>

 Expects an HTTP status 200 or 201 response from the backend. Any other
 status is treated as a failure.