diff --git a/.gitignore b/.gitignore index cc588ee8c..f6081d374 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .bundle .DS_Store .idea +/tests/.fog bin/* !bin/fog !bin/rdoc diff --git a/Rakefile b/Rakefile index 9b89d7017..1bb73af78 100644 --- a/Rakefile +++ b/Rakefile @@ -59,7 +59,7 @@ namespace :test do end task :test do - Rake::Task[:mock_tests].invoke && Rake::Task[:real_tests].invoke + Rake::Task[:mock_tests].invoke end def tests(mocked) diff --git a/lib/fog/atmos/models/storage/file.rb b/lib/fog/atmos/models/storage/file.rb index 7b74fc1b9..1a09a7a4b 100644 --- a/lib/fog/atmos/models/storage/file.rb +++ b/lib/fog/atmos/models/storage/file.rb @@ -57,20 +57,22 @@ module Fog # By default, expire in 5 years def public_url(expires = (Time.now + 5 * 365 * 24 * 60 * 60)) - requires :objectid - # TODO - more efficient method to get this? - storage = Fog::Storage.new(:provider => 'Atmos') - uri = URI::HTTP.build(:scheme => @prefix, :host => @storage_host, :port => @storage_port.to_i, :path => "/rest/objects/#{objectid}" ) - Fog::Storage.new(:provider => 'Atmos').uid + file = directory.files.head(key) + self.objectid = if file.present? then file.attributes['x-emc-meta'].scan(/objectid=(\w+),/).flatten[0] else nil end + if self.objectid.present? + uri = URI::HTTP.build(:scheme => connection.ssl? ? "http" : "https" , :host => connection.host, :port => connection.port.to_i, :path => "/rest/objects/#{self.objectid}" ) - sb = "GET\n" - sb += uri.path.downcase + "\n" - sb += storage.uid + "\n" - sb += String(expires.to_i()) + sb = "GET\n" + sb += uri.path.downcase + "\n" + sb += connection.uid + "\n" + sb += String(expires.to_i()) - signature = storage.sign( sb ) - uri.query = "uid=#{CGI::escape(storage.uid)}&expires=#{expires.to_i()}&signature=#{CGI::escape(signature)}" - uri.to_s + signature = connection.sign( sb ) + uri.query = "uid=#{CGI::escape(connection.uid)}&expires=#{expires.to_i()}&signature=#{CGI::escape(signature)}" + uri.to_s + else + nil + end end def save(options = {}) diff --git a/lib/fog/aws/cloud_watch.rb b/lib/fog/aws/cloud_watch.rb index b93753416..2bee06678 100644 --- a/lib/fog/aws/cloud_watch.rb +++ b/lib/fog/aws/cloud_watch.rb @@ -6,7 +6,7 @@ module Fog extend Fog::AWS::CredentialFetcher::ServiceMethods requires :aws_access_key_id, :aws_secret_access_key - recognizes :region, :host, :path, :port, :scheme, :persistent, :use_iam_profile, :aws_session_token, :aws_credentials_expire_at + recognizes :region, :host, :path, :port, :scheme, :persistent, :use_iam_profile, :aws_session_token, :aws_credentials_expire_at, :instrumentor, :instrumentor_name request_path 'fog/aws/requests/cloud_watch' @@ -94,6 +94,10 @@ module Fog setup_credentials(options) @connection_options = options[:connection_options] || {} + + @instrumentor = options[:instrumentor] + @instrumentor_name = options[:instrumentor_name] || 'fog.aws.cloud_watch' + options[:region] ||= 'us-east-1' @host = options[:host] || "monitoring.#{options[:region]}.amazonaws.com" @path = options[:path] || '/' @@ -136,6 +140,16 @@ module Fog } ) + if @instrumentor + @instrumentor.instrument("#{@instrumentor_name}.request", params) do + _request(body, idempotent, parser) + end + else + _request(body, idempotent, parser) + end + end + + def _request(body, idempotent, parser) @connection.request({ :body => body, :expects => 200, diff --git a/lib/fog/aws/models/auto_scaling/group.rb b/lib/fog/aws/models/auto_scaling/group.rb index 3353bcdb0..65b37ca62 100644 --- a/lib/fog/aws/models/auto_scaling/group.rb +++ b/lib/fog/aws/models/auto_scaling/group.rb @@ -121,9 +121,13 @@ module Fog # self #end - def destroy + def destroy(options = { :force => false }) requires :id - connection.delete_auto_scaling_group(id) + + opts = {} + opts.merge({'ForceDelete' => true}) if options[:force] + + connection.delete_auto_scaling_group(id, opts) end def update diff --git a/lib/fog/aws/parsers/cloud_watch/list_metrics.rb b/lib/fog/aws/parsers/cloud_watch/list_metrics.rb index 772509d33..75a935dd9 100644 --- a/lib/fog/aws/parsers/cloud_watch/list_metrics.rb +++ b/lib/fog/aws/parsers/cloud_watch/list_metrics.rb @@ -38,7 +38,7 @@ module Fog @metric[name] = value when 'Dimensions' @in_dimensions = false - when 'NextMarker' + when 'NextToken' @response['ListMetricsResult'][name] = value when 'RequestId' @response['ResponseMetadata'][name] = value diff --git a/lib/fog/aws/parsers/compute/describe_availability_zones.rb b/lib/fog/aws/parsers/compute/describe_availability_zones.rb index ab44cf0c7..e85612404 100644 --- a/lib/fog/aws/parsers/compute/describe_availability_zones.rb +++ b/lib/fog/aws/parsers/compute/describe_availability_zones.rb @@ -4,6 +4,13 @@ module Fog module AWS class DescribeAvailabilityZones < Fog::Parsers::Base + def start_element(name, attrs = []) + case name + when 'messageSet' + @in_message_set = true + end + super + end def reset @availability_zone = { 'messageSet' => [] } @@ -13,14 +20,18 @@ module Fog def end_element(name) case name when 'item' - @response['availabilityZoneInfo'] << @availability_zone - @availability_zone = { 'messageSet' => [] } + unless @in_message_set + @response['availabilityZoneInfo'] << @availability_zone + @availability_zone = { 'messageSet' => [] } + end when 'message' @availability_zone['messageSet'] << value when 'regionName', 'zoneName', 'zoneState' @availability_zone[name] = value when 'requestId' @response[name] = value + when 'messageSet' + @in_message_set = false end end diff --git a/lib/fog/aws/parsers/compute/describe_reserved_instances.rb b/lib/fog/aws/parsers/compute/describe_reserved_instances.rb index 1845acaa1..4a8d8fbe3 100644 --- a/lib/fog/aws/parsers/compute/describe_reserved_instances.rb +++ b/lib/fog/aws/parsers/compute/describe_reserved_instances.rb @@ -16,7 +16,7 @@ module Fog @reserved_instance[name] = value when 'duration', 'instanceCount' @reserved_instance[name] = value.to_i - when 'fixedPrice', 'amount' + when 'fixedPrice', 'amount', 'usagePrice' @reserved_instance[name] = value.to_f when 'item' @response['reservedInstancesSet'] << @reserved_instance diff --git a/lib/fog/aws/requests/glacier/create_archive.rb b/lib/fog/aws/requests/glacier/create_archive.rb index f8524df68..92bd62760 100644 --- a/lib/fog/aws/requests/glacier/create_archive.rb +++ b/lib/fog/aws/requests/glacier/create_archive.rb @@ -26,7 +26,7 @@ module Fog 'x-amz-content-sha256' => Digest::SHA256.hexdigest(body), 'x-amz-sha256-tree-hash' => Fog::AWS::Glacier::TreeHash.digest(body) } - headers['x-amz-archive-description'] = options['description'] if options['description'] + headers['x-amz-archive-description'] = Fog::AWS.escape(options['description']) if options['description'] request( :expects => 201, diff --git a/lib/fog/aws/requests/glacier/initiate_multipart_upload.rb b/lib/fog/aws/requests/glacier/initiate_multipart_upload.rb index 7c85b0288..e6cd207e6 100644 --- a/lib/fog/aws/requests/glacier/initiate_multipart_upload.rb +++ b/lib/fog/aws/requests/glacier/initiate_multipart_upload.rb @@ -23,7 +23,7 @@ module Fog path = "/#{account_id}/vaults/#{Fog::AWS.escape(name)}/multipart-uploads" headers = {'x-amz-part-size' => part_size.to_s} - headers['x-amz-archive-description'] = options['description'] if options['description'] + headers['x-amz-archive-description'] = Fog::AWS.escape(options['description']) if options['description'] request( :expects => 201, :headers => headers, diff --git a/lib/fog/brightbox/compute.rb b/lib/fog/brightbox/compute.rb index b299c0b5f..3a6e56430 100644 --- a/lib/fog/brightbox/compute.rb +++ b/lib/fog/brightbox/compute.rb @@ -209,7 +209,7 @@ module Fog def select_default_image return @default_image_id unless @default_image_id.nil? - all_images = Fog::Compute[:brightbox].list_images + all_images = list_images official_images = all_images.select {|img| img["official"] == true} ubuntu_lts_images = official_images.select {|img| img["name"] =~ /Ubuntu.*LTS/} ubuntu_lts_i686_images = ubuntu_lts_images.select {|img| img["arch"] == "i686"} diff --git a/lib/fog/brightbox/models/compute/server.rb b/lib/fog/brightbox/models/compute/server.rb index c1e2e9549..70cfab2a5 100644 --- a/lib/fog/brightbox/models/compute/server.rb +++ b/lib/fog/brightbox/models/compute/server.rb @@ -38,8 +38,10 @@ module Fog attribute :server_type def initialize(attributes={}) - self.image_id ||= Fog::Compute[:brightbox].default_image + # Call super first to initialize the 'connection' object for our default image super + # FIXME connection is actually not + self.image_id ||= connection.default_image end def zone_id diff --git a/lib/fog/google/storage.rb b/lib/fog/google/storage.rb index f2fc07f74..c8e09dc8c 100644 --- a/lib/fog/google/storage.rb +++ b/lib/fog/google/storage.rb @@ -243,7 +243,7 @@ DATA canonical_resource << "#{params[:path]}" canonical_resource << '?' for key in (params[:query] || {}).keys - if ['acl', 'location', 'logging', 'requestPayment', 'torrent', 'versions', 'versioning'].include?(key) + if ['acl', 'cors', 'location', 'logging', 'requestPayment', 'torrent', 'versions', 'versioning'].include?(key) canonical_resource << "#{key}&" end end diff --git a/lib/fog/openstack.rb b/lib/fog/openstack.rb index 1290b2b23..b52d78f86 100644 --- a/lib/fog/openstack.rb +++ b/lib/fog/openstack.rb @@ -95,7 +95,7 @@ module Fog req_body = { 'auth' => { 'passwordCredentials' => { - 'username' => @openstack_username, + 'username' => @openstack_username.to_s, 'password' => @openstack_api_key.to_s } } diff --git a/lib/fog/openstack/models/compute/server.rb b/lib/fog/openstack/models/compute/server.rb index 9f7e88cac..4cde80eb6 100644 --- a/lib/fog/openstack/models/compute/server.rb +++ b/lib/fog/openstack/models/compute/server.rb @@ -24,6 +24,8 @@ module Fog attribute :availability_zone attribute :user_data_encoded attribute :state, :aliases => 'status' + attribute :created, :type => :time + attribute :updated, :type => :time attribute :tenant_id attribute :user_id diff --git a/lib/fog/openstack/requests/compute/create_server.rb b/lib/fog/openstack/requests/compute/create_server.rb index 20ff57677..644bc3ca8 100644 --- a/lib/fog/openstack/requests/compute/create_server.rb +++ b/lib/fog/openstack/requests/compute/create_server.rb @@ -67,7 +67,9 @@ module Fog 'accessIPv4' => options['accessIPv4'] || "", 'accessIPv6' => options['accessIPv6'] || "", 'progress' => 0, - 'status' => 'BUILD' + 'status' => 'BUILD', + 'created' => '2012-09-27T00:04:18Z', + 'updated' => '2012-09-27T00:04:27Z', } self.data[:last_modified][:servers][data['id']] = Time.now diff --git a/lib/fog/vsphere/requests/compute/vm_clone.rb b/lib/fog/vsphere/requests/compute/vm_clone.rb index 5be484e6e..2c4998ca5 100644 --- a/lib/fog/vsphere/requests/compute/vm_clone.rb +++ b/lib/fog/vsphere/requests/compute/vm_clone.rb @@ -30,17 +30,43 @@ module Fog class Real include Shared + + # Clones a VM from a template or existing machine on your vSphere + # Server. + # + # ==== Parameters + # * options<~Hash>: + # * 'template_path'<~String> - *REQUIRED* The path to the machine you + # want to clone FROM. (Example: + # "/Datacenter/DataCenterNameHere/FolderNameHere/VMNameHere") + # * 'name'<~String> - *REQUIRED* The VMName of the Destination + # * 'resource_pool'<~String> - The resource pool on your datacenter + # cluster you want to use. + # * 'dest_folder'<~String> - Destination Folder of where 'name' will + # be placed on your cluster. *NOT TESTED OR VALIDATED* + # * 'power_on'<~Boolean> - Whether to power on machine after clone. + # Defaults to true. + # * 'wait'<~Boolean> - Whether the method should wait for the virtual + # machine to close finish cloning before returning information from + # vSphere. Returns the value of the machine if it finishes cloning + # in 150 seconds (1m30s) else it returns nil. 'wait' Defaults to nil. + # Saves a little time. + # * 'transform'<~String> - Not documented - see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html + # def vm_clone(options = {}) # Option handling options = vm_clone_check_options(options) + # Added for people still using options['path'] + template_path = options['path'] || options['template_path'] + notfound = lambda { raise Fog::Compute::Vsphere::NotFound, "Could not find VM template" } # Find the template in the folder. This is more efficient than # searching ALL VM's looking for the template. # Tap gets rid of the leading empty string and "Datacenters" element # and returns the array. - path_elements = options['path'].split('/').tap { |ary| ary.shift 2 } + path_elements = template_path.split('/').tap { |ary| ary.shift 2 } # The DC name itself. template_dc = path_elements.shift # If the first path element contains "vm" this denotes the vmFolder @@ -69,10 +95,10 @@ module Fog # Now find the template itself using the efficient find method vm_mob_ref = folder.find(template_name, RbVmomi::VIM::VirtualMachine) - # Now find _a_ resource pool to use for the clone - # (REVISIT: We need to support cloning into a specific RP) - - if ( vm_mob_ref.resourcePool == nil ) + # Now find _a_ resource pool to use for the clone if one is not specified + if ( options.has_key?('resource_pool') ) + resource_pool = options['resource_pool'] + elsif ( vm_mob_ref.resourcePool == nil ) # If the template is really a template then there is no associated resource pool, # so we need to find one using the template's parent host or cluster esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host'] @@ -125,7 +151,9 @@ module Fog clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec, :powerOn => options.has_key?('power_on') ? options['power_on'] : true, :template => false) - task = vm_mob_ref.CloneVM_Task(:folder => vm_mob_ref.parent, :name => options['name'], :spec => clone_spec) + task = vm_mob_ref.CloneVM_Task(:folder => options.has_key?('dest_folder') ? options['dest_folder'] : vm_mob_ref.parent, + :name => options['name'], + :spec => clone_spec) # Waiting for the VM to complete allows us to get the VirtulMachine # object of the new machine when it's done. It is HIGHLY recommended # to set 'wait' => true if your app wants to wait. Otherwise, you're diff --git a/tests/helper.rb b/tests/helper.rb index 6e9b26cfd..2b4b7ae6c 100644 --- a/tests/helper.rb +++ b/tests/helper.rb @@ -1,3 +1,6 @@ +ENV['FOG_RC'] = File.expand_path '../.fog', __FILE__ +ENV['FOG_CREDENTIAL'] = 'default' + require 'fog' require 'fog/bin' # for available_providers and registered_providers @@ -22,7 +25,7 @@ available_providers = Fog.available_providers.map {|provider| provider.downcase} unavailable_providers = all_providers - available_providers for provider in unavailable_providers - Formatador.display_line("[yellow]Skipping tests for [bold]#{provider}[/] [yellow]due to lacking credentials (add some to '~/.fog' to run them)[/]") + Formatador.display_line("[yellow]Skipping tests for [bold]#{provider}[/] [yellow]due to lacking credentials (add some to '#{Fog.credentials_path}' to run them)[/]") Thread.current[:tags] << ('-' << provider) end diff --git a/tests/openstack/requests/compute/server_tests.rb b/tests/openstack/requests/compute/server_tests.rb index 9f28b4961..a173e6aee 100644 --- a/tests/openstack/requests/compute/server_tests.rb +++ b/tests/openstack/requests/compute/server_tests.rb @@ -12,7 +12,9 @@ Shindo.tests('Fog::Compute[:openstack] | server requests', ['openstack']) do 'status' => String, 'accessIPv4' => Fog::Nullable::String, 'accessIPv6' => Fog::Nullable::String, - 'links' => Array + 'links' => Array, + 'created' => String, + 'updated' => String } @image_format = {