2013-12-12 12:16:38 -05:00
require 'fog/joyent'
require 'fog/joyent/errors'
module Fog
module Joyent
class Analytics < Fog :: Service
requires :joyent_username
recognizes :joyent_password
recognizes :joyent_url
recognizes :joyent_keyname
recognizes :joyent_keyfile
recognizes :joyent_keydata
recognizes :joyent_keyphrase
recognizes :joyent_version
request_path 'fog/joyent/requests/analytics'
request :describe_analytics
model_path 'fog/joyent/models/analytics'
collection :joyent_modules
model :joyent_module
2013-12-12 13:20:33 -05:00
collection :metrics
model :metric
2013-12-12 13:25:31 -05:00
collection :fields
model :field
2013-12-12 12:16:38 -05:00
class Mock
def self . data
@data || = Hash . new do | hash , key |
hash [ key ] = { }
end
end
def data
self . class . data
end
def initialize ( options = { } )
@joyent_username = options [ :joyent_username ] || Fog . credentials [ :joyent_username ]
@joyent_password = options [ :joyent_password ] || Fog . credentials [ :joyent_password ]
end
def request ( opts )
raise " Not Implemented "
end
end # Mock
class Real
def initialize ( options = { } )
@connection_options = options [ :connection_options ] || { }
@persistent = options [ :persistent ] || false
@joyent_url = options [ :joyent_url ] || 'https://us-sw-1.api.joyentcloud.com'
@joyent_version = options [ :joyent_version ] || '~7'
@joyent_username = options [ :joyent_username ]
unless @joyent_username
raise ArgumentError , " options[:joyent_username] required "
end
if options [ :joyent_keyname ]
@joyent_keyname = options [ :joyent_keyname ]
@joyent_keyphrase = options [ :joyent_keyphrase ]
@key_manager = Net :: SSH :: Authentication :: KeyManager . new ( nil , {
:keys_only = > true ,
:passphrase = > @joyent_keyphrase
} )
@header_method = method ( :header_for_signature_auth )
if options [ :joyent_keyfile ]
if File . exists? ( options [ :joyent_keyfile ] )
@joyent_keyfile = options [ :joyent_keyfile ]
@key_manager . add ( @joyent_keyfile )
else
raise ArgumentError , " options[:joyent_keyfile] provided does not exist. "
end
elsif options [ :joyent_keydata ]
if options [ :joyent_keydata ] . to_s . empty?
raise ArgumentError , 'options[:joyent_keydata] must not be blank'
else
@joyent_keydata = options [ :joyent_keydata ]
@key_manager . add_key_data ( @joyent_keydata )
end
end
elsif options [ :joyent_password ]
@joyent_password = options [ :joyent_password ]
@header_method = method ( :header_for_basic_auth )
else
raise ArgumentError , " Must provide either a joyent_password or joyent_keyname and joyent_keyfile pair "
end
@connection = Fog :: Connection . new (
@joyent_url ,
@persistent ,
@connection_options
)
end
def request ( opts = { } )
opts [ :headers ] = {
" X-Api-Version " = > @joyent_version ,
" Content-Type " = > " application/json " ,
" Accept " = > " application/json "
} . merge ( opts [ :headers ] || { } ) . merge ( @header_method . call )
if opts [ :body ]
opts [ :body ] = Fog :: JSON . encode ( opts [ :body ] )
end
response = @connection . request ( opts )
if response . headers [ " Content-Type " ] == " application/json "
response . body = json_decode ( response . body )
end
response
rescue Excon :: Errors :: HTTPStatusError = > e
raise_if_error! ( e . request , e . response )
end
private
def json_decode ( body )
parsed = Fog :: JSON . decode ( body )
decode_time_attrs ( parsed )
end
def header_for_basic_auth
{
" Authorization " = > " Basic #{ Base64 . encode64 ( " #{ @joyent_username } : #{ @joyent_password } " ) . delete ( " \r \n " ) } "
}
end
def header_for_signature_auth
date = Time . now . utc . httpdate
# Force KeyManager to load the key(s)
@key_manager . each_identity { }
key = @key_manager . known_identities . keys . first
sig = if key . kind_of? OpenSSL :: PKey :: RSA
@key_manager . sign ( key , date ) [ 15 .. - 1 ]
else
key = OpenSSL :: PKey :: DSA . new ( File . read ( @joyent_keyfile ) , @joyent_keyphrase )
key . sign ( 'sha1' , date )
end
key_id = " / #{ @joyent_username } /keys/ #{ @joyent_keyname } "
key_type = key . class . to_s . split ( '::' ) . last . downcase . to_sym
unless [ :rsa , :dsa ] . include? key_type
raise Joyent :: Errors :: Unauthorized . new ( 'Invalid key type -- only rsa or dsa key is supported' )
end
signature = Base64 . encode64 ( sig ) . delete ( " \r \n " )
{
" Date " = > date ,
" Authorization " = > " Signature keyId= \" #{ key_id } \" ,algorithm= \" #{ key_type } -sha1 \" #{ signature } "
}
rescue Net :: SSH :: Authentication :: KeyManagerError = > e
raise Joyent :: Errors :: Unauthorized . new ( 'SSH Signing Error: :#{e.message}' , e )
end
def decode_time_attrs ( obj )
if obj . kind_of? ( Hash )
obj [ " created " ] = Time . parse ( obj [ " created " ] ) unless obj [ " created " ] . nil? or obj [ " created " ] == ''
obj [ " updated " ] = Time . parse ( obj [ " updated " ] ) unless obj [ " updated " ] . nil? or obj [ " updated " ] == ''
elsif obj . kind_of? ( Array )
obj . map do | o |
decode_time_attrs ( o )
end
end
obj
end
def raise_if_error! ( request , response )
case response . status
when 401 then
raise Fog :: Compute :: Joyent :: Errors :: Unauthorized . new ( 'Invalid credentials were used' , request , response )
when 403 then
raise Fog :: Compute :: Joyent :: Errors :: Forbidden . new ( 'No permissions to the specified resource' , request , response )
when 404 then
raise Fog :: Compute :: Joyent :: Errors :: NotFound . new ( 'Requested resource was not found' , request , response )
when 405 then
raise Fog :: Compute :: Joyent :: Errors :: MethodNotAllowed . new ( 'Method not supported for the given resource' , request , response )
when 406 then
raise Fog :: Compute :: Joyent :: Errors :: NotAcceptable . new ( 'Try sending a different Accept header' , request , response )
when 409 then
raise Fog :: Compute :: Joyent :: Errors :: Conflict . new ( 'Most likely invalid or missing parameters' , request , response )
when 414 then
raise Fog :: Compute :: Joyent :: Errors :: RequestEntityTooLarge . new ( 'You sent too much data' , request , response )
when 415 then
raise Fog :: Compute :: Joyent :: Errors :: UnsupportedMediaType . new ( 'You encoded your request in a format we don\'t understand' , request , response )
when 420 then
raise Fog :: Compute :: Joyent :: Errors :: PolicyNotForfilled . new ( 'You are sending too many requests' , request , response )
when 449 then
raise Fog :: Compute :: Joyent :: Errors :: RetryWith . new ( 'Invalid API Version requested; try with a different API Version' , request , response )
when 503 then
raise Fog :: Compute :: Joyent :: Errors :: ServiceUnavailable . new ( 'Either there\'s no capacity in this datacenter, or we\'re in a maintenance window' , request , response )
end
end
end # Real
end
end
end