From 242941647e7ab704b7ad5b5d4e976016ca40b5f3 Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Tue, 17 Jul 2012 13:06:57 -0400 Subject: [PATCH 01/12] [aws|elasticache] Fix bug in cache cluster test --- tests/aws/requests/elasticache/cache_cluster_tests.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/aws/requests/elasticache/cache_cluster_tests.rb b/tests/aws/requests/elasticache/cache_cluster_tests.rb index 227e96f13..49337f93c 100644 --- a/tests/aws/requests/elasticache/cache_cluster_tests.rb +++ b/tests/aws/requests/elasticache/cache_cluster_tests.rb @@ -98,7 +98,7 @@ Shindo.tests('AWS::Elasticache | cache cluster requests', ['aws', 'elasticache'] body = AWS[:elasticache].modify_cache_cluster(c.id, { :num_nodes => NUM_NODES - 1, - :nodes_to_remove => node_id, + :nodes_to_remove => [node_id], :apply_immediately => true, }).body c.reload From 9ee9d04f6a6d2b36293fb45bf3ce2f41362712f1 Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Tue, 17 Jul 2012 13:07:20 -0400 Subject: [PATCH 02/12] [aws|elasticache] Remove erroneous whitespace trimming --- lib/fog/aws/models/elasticache/cluster.rb | 2 +- lib/fog/aws/requests/elasticache/create_cache_cluster.rb | 2 +- lib/fog/aws/requests/elasticache/modify_cache_cluster.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fog/aws/models/elasticache/cluster.rb b/lib/fog/aws/models/elasticache/cluster.rb index fde07058a..488393ca1 100644 --- a/lib/fog/aws/models/elasticache/cluster.rb +++ b/lib/fog/aws/models/elasticache/cluster.rb @@ -53,7 +53,7 @@ module Fog :auto_minor_version_upgrade => auto_upgrade, :engine => engine, :engine_version => engine_version, - :notification_topic_arn => (notification_config['TopicArn']).strip, + :notification_topic_arn => notification_config['TopicArn'], :port => port, :preferred_availablility_zone => zone, :preferred_maintenance_window => maintenance_window, diff --git a/lib/fog/aws/requests/elasticache/create_cache_cluster.rb b/lib/fog/aws/requests/elasticache/create_cache_cluster.rb index a41786034..147e0e5e3 100644 --- a/lib/fog/aws/requests/elasticache/create_cache_cluster.rb +++ b/lib/fog/aws/requests/elasticache/create_cache_cluster.rb @@ -43,7 +43,7 @@ module Fog 'AutoMinorVersionUpgrade' => options[:auto_minor_version_upgrade], 'CacheParameterGroupName' => options[:parameter_group_name], 'EngineVersion' => options[:engine_version], - 'NotificationTopicArn' => (options[:notification_topic_arn]).strip, + 'NotificationTopicArn' => options[:notification_topic_arn], 'Port' => options[:port], 'PreferredAvailabilityZone' => options[:preferred_availablility_zone], 'PreferredMaintenanceWindow' => options[:preferred_maintenance_window], diff --git a/lib/fog/aws/requests/elasticache/modify_cache_cluster.rb b/lib/fog/aws/requests/elasticache/modify_cache_cluster.rb index 1f5e8526f..ff18f72f4 100644 --- a/lib/fog/aws/requests/elasticache/modify_cache_cluster.rb +++ b/lib/fog/aws/requests/elasticache/modify_cache_cluster.rb @@ -51,7 +51,7 @@ module Fog 'AutoMinorVersionUpgrade' => options[:auto_minor_version_upgrade], 'CacheParameterGroupName' => options[:parameter_group_name], 'EngineVersion' => options[:engine_version], - 'NotificationTopicArn' => (options[:notification_topic_arn]).strip, + 'NotificationTopicArn' => options[:notification_topic_arn], 'NotificationTopicStatus' => options[:notification_topic_status], 'PreferredMaintenanceWindow' => options[:preferred_maintenance_window], :parser => Fog::Parsers::AWS::Elasticache::SingleCacheCluster.new From c47ba29b39abd8c83f9a00ae7c2c1b88c1c0e3d1 Mon Sep 17 00:00:00 2001 From: Josh Lane Date: Fri, 20 Jul 2012 09:50:28 -0700 Subject: [PATCH 03/12] [cloudstack|security_group] fix rule revoke mock --- lib/fog/cloudstack/models/compute/security_group_rule.rb | 9 +++++++-- .../requests/compute/authorize_security_group_egress.rb | 1 - .../requests/compute/authorize_security_group_ingress.rb | 1 - .../requests/compute/revoke_security_group_egress.rb | 5 ++--- .../requests/compute/revoke_security_group_ingress.rb | 5 ++--- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/fog/cloudstack/models/compute/security_group_rule.rb b/lib/fog/cloudstack/models/compute/security_group_rule.rb index 944a40c55..487a65f08 100644 --- a/lib/fog/cloudstack/models/compute/security_group_rule.rb +++ b/lib/fog/cloudstack/models/compute/security_group_rule.rb @@ -7,8 +7,8 @@ module Fog attribute :security_group_id, :type => :string attribute :protocol, :type => :string - attribute :start_port, :type => :integer - attribute :end_port, :type => :integer + attribute :start_port, :type => :integer, :aliases => 'startport' + attribute :end_port, :type => :integer, :aliases => 'endport' attribute :cidr, :type => :string attribute :direction, :type => :string @@ -19,6 +19,10 @@ module Fog job.successful? end + def port_range + (self.start_port..self.end_port) + end + def save requires :security_group_id, :cidr, :direction @@ -36,6 +40,7 @@ module Fog def reload requires :id, :security_group_id, :cidr + merge_attributes(security_group.rules.get(self.id)) end diff --git a/lib/fog/cloudstack/requests/compute/authorize_security_group_egress.rb b/lib/fog/cloudstack/requests/compute/authorize_security_group_egress.rb index fad6c8aa0..22c134117 100644 --- a/lib/fog/cloudstack/requests/compute/authorize_security_group_egress.rb +++ b/lib/fog/cloudstack/requests/compute/authorize_security_group_egress.rb @@ -59,7 +59,6 @@ module Fog } self.data[:jobs][job_id]= job - self.data[:security_groups][security_group_id] = security_group { "authorizesecuritygroupegressresponse" => { "jobid" => job_id } } end diff --git a/lib/fog/cloudstack/requests/compute/authorize_security_group_ingress.rb b/lib/fog/cloudstack/requests/compute/authorize_security_group_ingress.rb index 4244ffa46..3b86c114c 100644 --- a/lib/fog/cloudstack/requests/compute/authorize_security_group_ingress.rb +++ b/lib/fog/cloudstack/requests/compute/authorize_security_group_ingress.rb @@ -62,7 +62,6 @@ module Fog } self.data[:jobs][job_id]= job - self.data[:security_groups][security_group_id] = security_group { "authorizesecuritygroupingressresponse" => { "jobid" => job_id } } end diff --git a/lib/fog/cloudstack/requests/compute/revoke_security_group_egress.rb b/lib/fog/cloudstack/requests/compute/revoke_security_group_egress.rb index f88c654d8..f80c2ffbe 100644 --- a/lib/fog/cloudstack/requests/compute/revoke_security_group_egress.rb +++ b/lib/fog/cloudstack/requests/compute/revoke_security_group_egress.rb @@ -16,8 +16,8 @@ module Fog raise Fog::Compute::Cloudstack::BadRequest.new('Unable to execute API command missing parameter id') end - security_group_id, security_group = self.data[:security_groups].find do |id,group| - group['egressrule'] && group['egressrule'].delete_if { |r| r['id'] == security_group_rule_id } + security_group = self.data[:security_groups].values.find do |group| + (rule = (group['egressrule'] || []).find{|r| r['ruleid'] == security_group_rule_id}) && group['egressrule'].delete(rule) end job_id = Fog::Cloudstack.uuid @@ -33,7 +33,6 @@ module Fog } self.data[:jobs][job_id]= job - self.data[:security_groups][security_group_id] = security_group {"revokesecuritygroupegress" => { "jobid" => job_id }} end diff --git a/lib/fog/cloudstack/requests/compute/revoke_security_group_ingress.rb b/lib/fog/cloudstack/requests/compute/revoke_security_group_ingress.rb index fdbbab9d2..b5fcd82b2 100644 --- a/lib/fog/cloudstack/requests/compute/revoke_security_group_ingress.rb +++ b/lib/fog/cloudstack/requests/compute/revoke_security_group_ingress.rb @@ -19,8 +19,8 @@ module Fog raise Fog::Compute::Cloudstack::BadRequest.new('Unable to execute API command missing parameter id') end - security_group_id, security_group = self.data[:security_groups].find do |id,group| - group['ingressrule'] && group['ingressrule'].delete_if { |r| r['id'] == security_group_rule_id } + security_group = self.data[:security_groups].values.find do |group| + (rule = (group['ingressrule'] || []).find{|r| r['ruleid'] == security_group_rule_id}) && group['ingressrule'].delete(rule) end job_id = Fog::Cloudstack.uuid @@ -36,7 +36,6 @@ module Fog } self.data[:jobs][job_id]= job - self.data[:security_groups][security_group_id] = security_group {"revokesecuritygroupingress" => { "jobid" => job_id }} end From 3daf8e1568ac3087b8ca7788ca0907b68a7ec508 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 21 Jul 2012 14:00:34 -0700 Subject: [PATCH 04/12] Fixing typo bug in rackspace load balancer set_ssl_termination request --- .../rackspace/requests/load_balancers/set_ssl_termination.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/rackspace/requests/load_balancers/set_ssl_termination.rb b/lib/fog/rackspace/requests/load_balancers/set_ssl_termination.rb index 7ffbabf64..f4b69ae91 100644 --- a/lib/fog/rackspace/requests/load_balancers/set_ssl_termination.rb +++ b/lib/fog/rackspace/requests/load_balancers/set_ssl_termination.rb @@ -16,7 +16,7 @@ module Fog data['enabled'] = options[:enabled] end if options.has_key? :secure_traffic_only - data['secureTrafficOnly'] - options[:secure_traffic_only] + data['secureTrafficOnly'] = options[:secure_traffic_only] end request( :body => Fog::JSON.encode(data), From e9342d16e545c237066d2656be6e5f68bd633f84 Mon Sep 17 00:00:00 2001 From: Warren Bain Date: Sun, 22 Jul 2012 13:54:24 +1000 Subject: [PATCH 05/12] Recognize ninefold_api_url option for pre-production testing --- lib/fog/ninefold/compute.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/fog/ninefold/compute.rb b/lib/fog/ninefold/compute.rb index 859767c31..b5396aa1d 100644 --- a/lib/fog/ninefold/compute.rb +++ b/lib/fog/ninefold/compute.rb @@ -8,6 +8,7 @@ module Fog API_URL = "http://api.ninefold.com/compute/v1.0/" requires :ninefold_compute_key, :ninefold_compute_secret + recognizes :ninefold_api_url # allow us to specify non-prod environments model_path 'fog/ninefold/models/compute' model :server From 61ff93af32b76009651092cbd297a271b182b97e Mon Sep 17 00:00:00 2001 From: Adam Tanner Date: Sun, 22 Jul 2012 20:43:41 -0700 Subject: [PATCH 06/12] Local storage support for #public_url. --- lib/fog/local/models/storage/file.rb | 13 ++++++++- lib/fog/local/storage.rb | 24 +++++++++++++++++ tests/local/models/file_tests.rb | 40 ++++++++++++++++++++++++++++ tests/local/storage_tests.rb | 37 +++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 tests/local/models/file_tests.rb create mode 100644 tests/local/storage_tests.rb diff --git a/lib/fog/local/models/storage/file.rb b/lib/fog/local/models/storage/file.rb index 312328cb5..3140f72b0 100644 --- a/lib/fog/local/models/storage/file.rb +++ b/lib/fog/local/models/storage/file.rb @@ -12,6 +12,8 @@ module Fog # attribute :content_type, :aliases => 'Content-Type' attribute :last_modified, :aliases => 'Last-Modified' + require 'uri' + def body attributes[:body] ||= if last_modified collection.get(identity).body @@ -73,7 +75,16 @@ module Fog end def public_url - nil + requires :directory, :key + + if connection.endpoint + escaped_directory = URI.escape(directory.key) + escaped_key = URI.escape(key) + + ::File.join(connection.endpoint, escaped_directory, escaped_key) + else + nil + end end def save(options = {}) diff --git a/lib/fog/local/storage.rb b/lib/fog/local/storage.rb index 154cc3915..63555b3a1 100644 --- a/lib/fog/local/storage.rb +++ b/lib/fog/local/storage.rb @@ -6,6 +6,7 @@ module Fog class Local < Fog::Service requires :local_root + recognizes :endpoint, :scheme, :host, :port, :path model_path 'fog/local/models/storage' collection :directories @@ -13,8 +14,12 @@ module Fog model :file collection :files + require 'uri' + class Mock + attr_reader :endpoint + def self.data @data ||= Hash.new do |hash, key| hash[key] = {} @@ -30,6 +35,8 @@ module Fog require 'mime/types' @local_root = ::File.expand_path(options[:local_root]) + + @endpoint = options[:endpoint] || build_endpoint_from_options(options) end def data @@ -48,13 +55,23 @@ module Fog self.class.data.delete(@local_root) end + private + def build_endpoint_from_options(options) + return unless options[:host] + + URI::Generic.build(options).to_s + end end class Real + attr_reader :endpoint + def initialize(options={}) require 'mime/types' @local_root = ::File.expand_path(options[:local_root]) + + @endpoint = options[:endpoint] || build_endpoint_from_options(options) end def local_root @@ -72,6 +89,13 @@ module Fog ::FileUtils.mkdir_p(::File.dirname(target_path)) ::FileUtils.copy_file(source_path, target_path) end + + private + def build_endpoint_from_options(options) + return unless options[:host] + + URI::Generic.build(options).to_s + end end end diff --git a/tests/local/models/file_tests.rb b/tests/local/models/file_tests.rb new file mode 100644 index 000000000..f4dc5d3d1 --- /dev/null +++ b/tests/local/models/file_tests.rb @@ -0,0 +1,40 @@ +Shindo.tests('Storage[:local] | file', [:local]) do + before do + @options = { :local_root => '~/.fog' } + end + + tests('#public_url') do + tests('when connection has an endpoint'). + returns('http://example.com/files/directory/file.txt') do + @options[:endpoint] = 'http://example.com/files' + + connection = Fog::Storage::Local.new(@options) + directory = connection.directories.new(:key => 'directory') + file = directory.files.new(:key => 'file.txt') + + file.public_url + end + + tests('when connection has no endpoint'). + returns(nil) do + @options[:endpoint] = nil + + connection = Fog::Storage::Local.new(@options) + directory = connection.directories.new(:key => 'directory') + file = directory.files.new(:key => 'file.txt') + + file.public_url + end + + tests('when file path has escapable characters'). + returns('http://example.com/files/my%20directory/my%20file.txt') do + @options[:endpoint] = 'http://example.com/files' + + connection = Fog::Storage::Local.new(@options) + directory = connection.directories.new(:key => 'my directory') + file = directory.files.new(:key => 'my file.txt') + + file.public_url + end + end +end \ No newline at end of file diff --git a/tests/local/storage_tests.rb b/tests/local/storage_tests.rb new file mode 100644 index 000000000..e1755bd0b --- /dev/null +++ b/tests/local/storage_tests.rb @@ -0,0 +1,37 @@ +Shindo.tests('Local | storage') do + before do + @options = { :local_root => "~/.fog" } + end + + tests('#endpoint') do + tests('when no endpoint is provided'). + returns(nil) do + Fog::Storage::Local.new(@options).endpoint + end + + tests('when no host is provided'). + returns(nil) do + @options[:scheme] = 'http' + @options[:path] = '/files' + @options[:port] = 80 + + Fog::Storage::Local.new(@options).endpoint + end + + tests('when endpoint is provided'). + returns('http://example.com/files') do + @options[:endpoint] = 'http://example.com/files' + + Fog::Storage::Local.new(@options).endpoint + end + + tests('when at least host option is provided'). + returns('http://example.com/files') do + @options[:scheme] = 'http' + @options[:host] = 'example.com' + @options[:path] = '/files' + + Fog::Storage::Local.new(@options).endpoint + end + end +end \ No newline at end of file From 00734a64489763a6dc8d368c0788d3c222e30831 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 20 Jul 2012 14:12:28 -0700 Subject: [PATCH 07/12] Default to being less pessimistic about excon - It limits using more recent gems through a project - If there are explicit breaking changes in future versions, then add an additional <= --- fog.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fog.gemspec b/fog.gemspec index 2fd9688e5..2c7bb7089 100644 --- a/fog.gemspec +++ b/fog.gemspec @@ -42,7 +42,7 @@ Gem::Specification.new do |s| ## List your runtime dependencies here. Runtime dependencies are those ## that are needed for an end user to actually USE your code. s.add_dependency('builder') - s.add_dependency('excon', '~>0.14.0') + s.add_dependency('excon', '~>0.14') s.add_dependency('formatador', '~>0.2.0') s.add_dependency('multi_json', '~>1.0') s.add_dependency('mime-types') From 053551cf739e3b099fc8b1a37ee85ef94370a156 Mon Sep 17 00:00:00 2001 From: Edward Muller Date: Mon, 23 Jul 2012 13:46:55 -0700 Subject: [PATCH 08/12] Only dup @attributes if it's not nil --- lib/fog/core/attributes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/core/attributes.rb b/lib/fog/core/attributes.rb index 3a72dd55b..ceadc8c3e 100644 --- a/lib/fog/core/attributes.rb +++ b/lib/fog/core/attributes.rb @@ -186,7 +186,7 @@ module Fog end def dup_attributes! - @attributes = @attributes.dup + @attributes = @attributes.dup if @attributes end private From e2820d2c0381b08c927c1dd5676379d0b2bc94aa Mon Sep 17 00:00:00 2001 From: Edward Muller Date: Mon, 23 Jul 2012 13:47:25 -0700 Subject: [PATCH 09/12] each based pagination for Fog::AWS::IAM#users --- lib/fog/aws/models/iam/users.rb | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/fog/aws/models/iam/users.rb b/lib/fog/aws/models/iam/users.rb index af6a6d23a..f5b5dc1a7 100644 --- a/lib/fog/aws/models/iam/users.rb +++ b/lib/fog/aws/models/iam/users.rb @@ -7,11 +7,16 @@ module Fog class Users < Fog::Collection + attribute :is_truncated, :aliases => 'IsTruncated' + attribute :marker, :aliases => 'Marker' + model Fog::AWS::IAM::User - def all - data = connection.list_users.body['Users'] - load(data) # data is an array of attribute hashes + def all(options = {}) + merge_attributes(options) + data = connection.list_users(options).body + merge_attributes('IsTruncated' => data['IsTruncated'], 'Marker' => data['Marker']) + load(data['Users']) # data is an array of attribute hashes end def get(identity) @@ -21,7 +26,24 @@ module Fog nil end + alias :each_user_this_page :each + + def each + if !block_given? + self + else + subset = dup.all + + subset.each_user_this_page {|f| yield f} + while subset.is_truncated + subset = subset.all('Marker' => subset.marker, 'MaxItems' => 1000) + subset.each_user_this_page {|f| yield f} + end + + self + end + end end end end -end \ No newline at end of file +end From dbab97a833b79e770dce5a0d3547cd36a3cdda45 Mon Sep 17 00:00:00 2001 From: Irio Irineu Musskopf Junior Date: Tue, 24 Jul 2012 17:45:09 -0300 Subject: [PATCH 10/12] Add Sao Paulo server to Amazon RDS known regions --- lib/fog/aws/rds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/aws/rds.rb b/lib/fog/aws/rds.rb index 26680fbda..4619733b6 100644 --- a/lib/fog/aws/rds.rb +++ b/lib/fog/aws/rds.rb @@ -90,7 +90,7 @@ module Fog @use_iam_profile = options[:use_iam_profile] @region = options[:region] || 'us-east-1' - unless ['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1', 'us-west-2'].include?(@region) + unless ['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1', 'us-west-2', 'sa-east-1'].include?(@region) raise ArgumentError, "Unknown region: #{@region.inspect}" end From cb52f35309b000d87f876b8e9ced85f85bba80a7 Mon Sep 17 00:00:00 2001 From: Irio Irineu Musskopf Junior Date: Tue, 24 Jul 2012 17:47:14 -0300 Subject: [PATCH 11/12] Add Sao Paulo server to Amazon SQS known regions --- lib/fog/aws/sqs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/aws/sqs.rb b/lib/fog/aws/sqs.rb index 4cc09d6b2..211f21b5b 100644 --- a/lib/fog/aws/sqs.rb +++ b/lib/fog/aws/sqs.rb @@ -40,7 +40,7 @@ module Fog setup_credentials(options) @region = options[:region] || 'us-east-1' - unless ['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1', 'us-west-2'].include?(@region) + unless ['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1', 'us-west-2', 'sa-east-1'].include?(@region) raise ArgumentError, "Unknown region: #{@region.inspect}" end end From 73467e71ea73145113893a170eac2b61b65df0c1 Mon Sep 17 00:00:00 2001 From: Dan Peterson Date: Tue, 26 Jun 2012 21:49:49 -0300 Subject: [PATCH 12/12] [dynect|dns] No more recursion when polling jobs. Raise an error if the body indicates failure. --- lib/fog/dynect/dns.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/fog/dynect/dns.rb b/lib/fog/dynect/dns.rb index c32b3591e..6c7f5d8e1 100644 --- a/lib/fog/dynect/dns.rb +++ b/lib/fog/dynect/dns.rb @@ -65,7 +65,7 @@ module Fog @dynect_password = options[:dynect_password] @connection_options = options[:connection_options] || {} - @host = "api2.dynect.net" + @host = 'api2.dynect.net' @port = options[:port] || 443 @path = options[:path] || '/REST' @persistent = options[:persistent] || false @@ -86,16 +86,25 @@ module Fog params[:headers] ||= {} params[:headers]['Content-Type'] = 'application/json' params[:headers]['API-Version'] = @version - params[:headers]['Auth-Token'] = auth_token unless params[:path] == "Session" + params[:headers]['Auth-Token'] = auth_token unless params[:path] == 'Session' params[:path] = "#{@path}/#{params[:path]}" unless params[:path] =~ %r{^#{Regexp.escape(@path)}/} + response = @connection.request(params.merge!({:host => @host})) - if response.status == 307 - response = poll_job(response) - elsif !response.body.empty? + if response.body.empty? + response.body = {} + else response.body = Fog::JSON.decode(response.body) end + if response.body['status'] == 'failure' + raise Error, response.body['msgs'].first['INFO'] + end + + if response.status == 307 && params[:path] !~ %r{^/REST/Job/} + response = poll_job(response) + end + response rescue Excon::Errors::HTTPStatusError => error if @auth_token && error.message =~ /login: (Bad or expired credentials|inactivity logout)/