diff --git a/lib/fog/bin.rb b/lib/fog/bin.rb index 81e995cea..383a811b4 100644 --- a/lib/fog/bin.rb +++ b/lib/fog/bin.rb @@ -64,6 +64,7 @@ require 'fog/bin/google' require 'fog/bin/linode' require 'fog/bin/local' require 'fog/bin/new_servers' +require 'fog/bin/ninefold' require 'fog/bin/rackspace' require 'fog/bin/slicehost' require 'fog/bin/stormondemand' diff --git a/lib/fog/bin/ninefold.rb b/lib/fog/bin/ninefold.rb new file mode 100644 index 000000000..703c929c8 --- /dev/null +++ b/lib/fog/bin/ninefold.rb @@ -0,0 +1,30 @@ +class Ninefold < Fog::Bin + class << self + + def class_for(key) + case key + when :compute + Fog::Ninefold::Compute + else + raise ArgumentError, "Unsupported #{self} service: #{key}" + end + end + + def [](service) + @@connections ||= Hash.new do |hash, key| + hash[key] = case key + when :compute + Fog::Compute.new(:provider => 'Ninefold') + else + raise ArgumentError, "Unrecognized service: #{service}" + end + end + @@connections[service] + end + + def services + Fog::Ninefold.services + end + + end +end diff --git a/lib/fog/compute.rb b/lib/fog/compute.rb index 3863aadec..30d8e44fa 100644 --- a/lib/fog/compute.rb +++ b/lib/fog/compute.rb @@ -25,6 +25,9 @@ module Fog when 'NewServers' require 'fog/compute/new_servers' Fog::NewServers::Compute.new(attributes) + when 'Ninefold' + require 'fog/compute/ninefold' + Fog::Ninefold::Compute.new(attributes) when 'Rackspace' require 'fog/compute/rackspace' Fog::Rackspace::Compute.new(attributes) diff --git a/lib/fog/compute/ninefold.rb b/lib/fog/compute/ninefold.rb new file mode 100644 index 000000000..d3d1bb294 --- /dev/null +++ b/lib/fog/compute/ninefold.rb @@ -0,0 +1,147 @@ +module Fog + module Ninefold + class Compute < Fog::Service + + API_URL = "http://api.ninefold.com/compute/v1.0/" + + requires :ninefold_compute_key, :ninefold_compute_secret + #recognizes :brightbox_auth_url, :brightbox_api_url + recognizes :provider # remove post deprecation + + model_path 'fog/compute/models/ninefold' + #collection :servers + #model :server + #collection :flavors + #model :flavor + #collection :images + #model :image + #collection :load_balancers + #model :load_balancer + #collection :zones + #model :zone + #collection :cloud_ips + #model :cloud_ip + #collection :users + #model :user + + request_path 'fog/compute/requests/ninefold' + request :deploy_virtual_machine + #request :activate_console_server + #request :add_listeners_load_balancer + #request :add_nodes_load_balancer + #request :create_api_client + #request :create_cloud_ip + #request :create_image + #request :create_load_balancer + #request :destroy_api_client + #request :destroy_cloud_ip + #request :destroy_image + #request :destroy_load_balancer + #request :destroy_server + #request :get_account + #request :get_api_client + #request :get_cloud_ip + #request :get_image + #request :get_interface + #request :get_load_balancer + #request :get_server + #request :get_server_type + #request :get_user + #request :get_zone + #request :list_api_clients + #request :list_cloud_ips + #request :list_images + #request :list_load_balancers + #request :list_server_types + #request :list_servers + #request :list_users + #request :list_zones + #request :map_cloud_ip + #request :remove_listeners_load_balancer + #request :remove_nodes_load_balancer + #request :reset_ftp_password_account + #request :resize_server + #request :shutdown_server + #request :snapshot_server + #request :start_server + #request :stop_server + #request :unmap_cloud_ip + #request :update_account + #request :update_api_client + #request :update_image + #request :update_load_balancer + #request :update_server + #request :update_user + + class Mock + + def initialize(options) + unless options.delete(:provider) + location = caller.first + warning = "[yellow][WARN] Fog::Ninefold::Compute.new is deprecated, use Fog::Compute.new(:provider => 'Ninefold') instead[/]" + warning << " [light_black](" << location << ")[/] " + Formatador.display_line(warning) + end + + @brightbox_client_id = options[:brightbox_client_id] || Fog.credentials[:brightbox_client_id] + @brightbox_secret = options[:brightbox_secret] || Fog.credentials[:brightbox_secret] + end + + def request(options) + raise "Not implemented" + end + end + + class Real + + def initialize(options) + unless options.delete(:provider) + location = caller.first + warning = "[yellow][WARN] Fog::Ninefold::Compute.new is deprecated, use Fog::Compute.new(:provider => 'Ninefold') instead[/]" + warning << " [light_black](" << location << ")[/] " + Formatador.display_line(warning) + end + + require "json" + + @api_url = options[:ninefold_api_url] || Fog.credentials[:ninefold_api_url] || API_URL + @ninefold_compute_key = options[:ninefold_compute_key] || Fog.credentials[:ninefold_compute_key] + @ninefold_compute_secret = options[:ninefold_compute_secret] || Fog.credentials[:ninefold_compute_secret] + @connection = Fog::Connection.new(@api_url) + end + + def request(command, params, options) + params["response"] = "json" + req = "apiKey=#{@ninefold_compute_key}&command=#{command}&" + req += URI.escape(params.sort.collect{|e| "#{e[0].to_s}=#{e[1].to_s}"}.join('&')) + encoded_signature = url_escape(encode_signature(req)) + + options = { + :expects => 200, + :method => 'GET', + :query => "#{req}&signature=#{encoded_signature}" + }.merge(options) + + begin + response = @connection.request(options) + end + unless response.body.empty? + response = JSON.parse(response.body) + end + end + + private + def url_escape(string) + string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do + '%' + $1.unpack('H2' * $1.size).join('%').upcase + end.tr(' ', '+') + end + + def encode_signature(data) + p @ninefold_compute_secret + Base64.encode64(OpenSSL::HMAC.digest('sha1', @ninefold_compute_secret, URI.encode(data.downcase).gsub('+', '%20'))).chomp + end + end + end + end +end diff --git a/lib/fog/compute/requests/ninefold/deploy_virtual_machine.rb b/lib/fog/compute/requests/ninefold/deploy_virtual_machine.rb new file mode 100644 index 000000000..402bd0add --- /dev/null +++ b/lib/fog/compute/requests/ninefold/deploy_virtual_machine.rb @@ -0,0 +1,13 @@ +module Fog + module Ninefold + class Compute + class Real + + def deploy_virtual_machine(options = {}) + request('deployVirtualMachine', options, :expects => [202]) + end + + end + end + end +end diff --git a/lib/fog/providers.rb b/lib/fog/providers.rb index 30bb74f04..43e4df3a7 100644 --- a/lib/fog/providers.rb +++ b/lib/fog/providers.rb @@ -17,6 +17,7 @@ require 'fog/providers/google' require 'fog/providers/linode' require 'fog/providers/local' require 'fog/providers/new_servers' +require 'fog/providers/ninefold' require 'fog/providers/rackspace' require 'fog/providers/slicehost' require 'fog/providers/storm_on_demand' diff --git a/lib/fog/providers/ninefold.rb b/lib/fog/providers/ninefold.rb new file mode 100644 index 000000000..b1a3ae7ba --- /dev/null +++ b/lib/fog/providers/ninefold.rb @@ -0,0 +1,11 @@ +require 'fog/core' + +module Fog + module Ninefold + + extend Fog::Provider + + service(:compute, 'compute/ninefold') + + end +end diff --git a/tests/compute/helper.rb b/tests/compute/helper.rb index 07aec7dd3..508721995 100644 --- a/tests/compute/helper.rb +++ b/tests/compute/helper.rb @@ -17,6 +17,9 @@ def compute_providers }, :mocked => false }, + Ninefold => { + :mocked => false + }, Rackspace => { :server_attributes => { :image_id => 49, # image 49 = Ubuntu 10.04 LTS (lucid) diff --git a/tests/compute/requests/ninefold/server_tests.rb b/tests/compute/requests/ninefold/server_tests.rb new file mode 100644 index 000000000..411423551 --- /dev/null +++ b/tests/compute/requests/ninefold/server_tests.rb @@ -0,0 +1,16 @@ +Shindo.tests('Ninfold::Compute | server requests', ['ninefold']) do + + tests('success') do + + end + + tests('failure') do + + tests("#deploy_virtual_machine()").raises(Excon::Errors::HTTPStatusError) do + pending if Fog.mocking? + Ninefold[:compute].deploy_virtual_machine + end + + end + +end diff --git a/tests/helper.rb b/tests/helper.rb index e87f6c183..0310e1c27 100644 --- a/tests/helper.rb +++ b/tests/helper.rb @@ -8,7 +8,7 @@ def lorem_file end # check to see which credentials are available and add others to the skipped tags list -all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'dnsmadeeasy', 'ecloud', 'gogrid', 'google', 'linode', 'local', 'newservers', 'rackspace', 'slicehost', 'stormondemand', 'voxel', 'zerigo'] +all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'dnsmadeeasy', 'ecloud', 'gogrid', 'google', 'linode', 'local', 'ninefold', 'newservers', 'rackspace', 'slicehost', 'stormondemand', 'voxel', 'zerigo'] available_providers = Fog.available_providers.map {|provider| provider.downcase} for provider in (all_providers - available_providers) Formatador.display_line("[yellow]Skipping tests for [bold]#{provider}[/] [yellow]due to lacking credentials (add some to '~/.fog' to run them)[/]")