right_cloud_api_base 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/HISTORY +2 -0
  3. data/LICENSE +19 -0
  4. data/README.md +14 -0
  5. data/Rakefile +37 -0
  6. data/lib/base/api_manager.rb +707 -0
  7. data/lib/base/helpers/cloud_api_logger.rb +214 -0
  8. data/lib/base/helpers/http_headers.rb +239 -0
  9. data/lib/base/helpers/http_parent.rb +103 -0
  10. data/lib/base/helpers/http_request.rb +173 -0
  11. data/lib/base/helpers/http_response.rb +122 -0
  12. data/lib/base/helpers/net_http_patch.rb +31 -0
  13. data/lib/base/helpers/query_api_patterns.rb +862 -0
  14. data/lib/base/helpers/support.rb +270 -0
  15. data/lib/base/helpers/support.xml.rb +306 -0
  16. data/lib/base/helpers/utils.rb +380 -0
  17. data/lib/base/manager.rb +122 -0
  18. data/lib/base/parsers/json.rb +38 -0
  19. data/lib/base/parsers/plain.rb +36 -0
  20. data/lib/base/parsers/rexml.rb +83 -0
  21. data/lib/base/parsers/sax.rb +200 -0
  22. data/lib/base/routines/cache_validator.rb +184 -0
  23. data/lib/base/routines/connection_proxies/net_http_persistent_proxy.rb +194 -0
  24. data/lib/base/routines/connection_proxies/right_http_connection_proxy.rb +224 -0
  25. data/lib/base/routines/connection_proxy.rb +66 -0
  26. data/lib/base/routines/request_analyzer.rb +122 -0
  27. data/lib/base/routines/request_generator.rb +48 -0
  28. data/lib/base/routines/request_initializer.rb +52 -0
  29. data/lib/base/routines/response_analyzer.rb +152 -0
  30. data/lib/base/routines/response_parser.rb +79 -0
  31. data/lib/base/routines/result_wrapper.rb +75 -0
  32. data/lib/base/routines/retry_manager.rb +106 -0
  33. data/lib/base/routines/routine.rb +98 -0
  34. data/lib/right_cloud_api_base.rb +72 -0
  35. data/lib/right_cloud_api_base_version.rb +37 -0
  36. data/right_cloud_api_base.gemspec +63 -0
  37. data/spec/helpers/query_api_pattern_spec.rb +312 -0
  38. data/spec/helpers/support_spec.rb +211 -0
  39. data/spec/helpers/support_xml_spec.rb +207 -0
  40. data/spec/helpers/utils_spec.rb +179 -0
  41. data/spec/routines/connection_proxies/test_net_http_persistent_proxy_spec.rb +143 -0
  42. data/spec/routines/test_cache_validator_spec.rb +152 -0
  43. data/spec/routines/test_connection_proxy_spec.rb +44 -0
  44. data/spec/routines/test_request_analyzer_spec.rb +106 -0
  45. data/spec/routines/test_response_analyzer_spec.rb +132 -0
  46. data/spec/routines/test_response_parser_spec.rb +228 -0
  47. data/spec/routines/test_result_wrapper_spec.rb +63 -0
  48. data/spec/routines/test_retry_manager_spec.rb +84 -0
  49. data/spec/spec_helper.rb +15 -0
  50. metadata +215 -0
@@ -0,0 +1,79 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module RightScale
25
+ module CloudApi
26
+
27
+ # The routine parses the current response.
28
+ #
29
+ # The supportes content-types are: xml and json.
30
+ # In the case of any other content-type it does nothing.
31
+ #
32
+ class ResponseParser < Routine
33
+
34
+ # Main entry point.
35
+ #
36
+ def process
37
+ # There is no way to parse an IO response
38
+ return nil if data[:response][:instance].is_io?
39
+
40
+ xml_parser = Utils::get_xml_parser_class(data[:options][:xml_parser])
41
+ content_type = (data[:response][:instance].headers || {})["content-type"].to_s
42
+ body = data[:response][:instance].body.to_s
43
+
44
+ # If it was explicitly requested not to parse the response then return it as is.
45
+ if data[:options][:raw_response]
46
+ data[:result] = body
47
+ return
48
+ end
49
+
50
+ # Find the appropriate parser.
51
+ parser = if body._blank?
52
+ Parser::Plain
53
+ else
54
+ case content_type
55
+ when /xml/ then xml_parser
56
+ when /json|javascript/ then Parser::Json
57
+ else
58
+ if data[:response][:instance].body.to_s[/\A<\?xml /]
59
+ # Sometimes Amazon does not set a proper header
60
+ xml_parser
61
+ else
62
+ Parser::Plain
63
+ end
64
+ end
65
+ end
66
+ # Parse the response
67
+ with_timer("Response parsing with #{parser}") do
68
+ options = {}
69
+ options[:encoding] = 'UTF-8' if /utf-8/i === content_type
70
+ #
71
+ cloud_api_logger.log("Attempting to parse cloud response with: '#{options[:encoding] || 'DEFAULT'}' encoding", :response_parser)
72
+ data[:response][:parsed] = parser::parse(body, options)
73
+ end
74
+ data[:result] = data[:response][:parsed]
75
+ end
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,75 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module RightScale
25
+ module CloudApi
26
+
27
+ # The Routine adds metadata to the result.
28
+ #
29
+ # @example:
30
+ # response = ec2.DescribeSecurityGroups #=> A list of SecurityGroups
31
+ # response.metadata #=>
32
+ # {:headers=>
33
+ # {"content-type"=>["text/xml;charset=UTF-8"],
34
+ # "transfer-encoding"=>["chunked"],
35
+ # "date"=>["Fri, 22 Feb 2013 00:02:43 GMT"],
36
+ # "server"=>["AmazonEC2"]},
37
+ # :code=>"200",
38
+ # :cache=>
39
+ # {:key=>"DescribeSecurityGroups",
40
+ # :record=>
41
+ # {:timestamp=>2013-02-22 00:02:44 UTC,
42
+ # :md5=>"0e3e12e1c18237d9f9510e90e7b8950e",
43
+ # :hits=>0}}}
44
+ #
45
+ class ResultWrapper < Routine
46
+
47
+ class Result < BlankSlate
48
+ attr_reader :metadata
49
+
50
+ def initialize(response, metadata)
51
+ @response = response
52
+ @metadata = metadata
53
+ end
54
+
55
+ # Feed all the missing methods to the original object.
56
+ def method_missing(method, *params, &block)
57
+ @response.send(method, *params, &block)
58
+ end
59
+ end
60
+
61
+ # Main entry point.
62
+ #
63
+ def process
64
+ cache = data._at(:vars, :cache, :default => nil)
65
+ metadata = {}
66
+ metadata[:headers] = data[:response][:instance].headers
67
+ metadata[:code] = data[:response][:instance].code
68
+ metadata[:cache] = cache if cache
69
+ #
70
+ data[:result] = Result::new(data[:result], metadata)
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,106 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module RightScale
25
+ module CloudApi
26
+
27
+ # The routine is responsible for retries/reiterations.
28
+ #
29
+ # If retries are enabled then a singe API call may perform upto DEFAULT_RETRY_COUNT request
30
+ # attempts who may take upto DEFAULT_REITERATION_TIME secsons.
31
+ #
32
+ class RetryManager < Routine
33
+ class Error < CloudApi::HttpError
34
+ end
35
+
36
+ DEFAULT_RETRY_COUNT = 2
37
+ DEFAULT_REITERATION_TIME = 10
38
+ DEFAULT_SLEEP_TIME = 0.2
39
+
40
+ # Retries manager.
41
+ #
42
+ # The manager usually takes the very first position in routines chain.
43
+ # It just increments its counters if we did not reach a possible count of retries or
44
+ # complains if there are no attempts left or if API request time is over.
45
+ #
46
+ # There are 2 possible reasons for a retry to be performed:
47
+ # 1. There was a redirect request (HTTP 3xx code)
48
+ # 2. There was an error (HTTP 5xx, 4xx) and
49
+ #
50
+ def process
51
+ retry_options = data[:options][:retry] || {}
52
+ max_retry_count = retry_options[:count] || DEFAULT_RETRY_COUNT
53
+ reiteration_time = retry_options[:reiteration_time] || DEFAULT_REITERATION_TIME
54
+ sleep_time = retry_options[:sleep_time] || DEFAULT_SLEEP_TIME
55
+
56
+ # Initialize things on the first run for the current request.
57
+ unless data[:vars][:retry]
58
+ data[:vars][:retry] = {}
59
+ data[:vars][:retry][:count] = 0
60
+ data[:vars][:retry][:sleep_time] = 0
61
+ # if body is a IO object - remember its initial position in a file
62
+ data[:vars][:retry][:orig_body_stream_pos] = data[:request][:body].is_a?(IO) && data[:request][:body].pos
63
+ else
64
+ # Increment retry attempts count
65
+ data[:vars][:retry][:count] += 1
66
+ end
67
+
68
+ # Complain on any issue
69
+ if max_retry_count < @data[:vars][:retry][:count]
70
+ error_message = "RetryManager: No more retries left."
71
+ elsif Time.now > @data[:vars][:system][:started_at] + reiteration_time
72
+ error_message = "RetryManager: Retry timeout of #{reiteration_time} seconds has been reached."
73
+ end
74
+
75
+ # Raise exception if request runs out-of-time or attempts.
76
+ if error_message
77
+ http_data = @data[:vars][:retry][:http]
78
+ http_code = http_data && http_data[:code]
79
+ http_message = http_data && http_data[:message]
80
+ error_message = "#{http_message}\n#{error_message}" if http_message
81
+ raise Error::new(http_code, error_message)
82
+ end
83
+
84
+ # Continue (with a delay when needed)
85
+ if data[:vars][:retry][:sleep_time] > 0
86
+ cloud_api_logger.log("Sleeping for #{data[:vars][:retry][:sleep_time]} seconds before retry attempt ##{data[:vars][:retry][:count]}", :retry_manager)
87
+ sleep data[:vars][:retry][:sleep_time]
88
+ data[:vars][:retry][:sleep_time] *= 2
89
+ else
90
+ data[:vars][:retry][:sleep_time] = sleep_time
91
+ end
92
+
93
+ # Restore file pointer in IO body case.
94
+ if data[:request][:instance] &&
95
+ data[:request][:instance].is_io? &&
96
+ data[:request][:instance].body.respond_to?('pos') &&
97
+ data[:request][:instance].body.respond_to?('pos=') &&
98
+ data[:request][:instance].body.pos != data[:vars][:retry][:orig_body_stream_pos]
99
+ cloud_api_logger.log("Restoring file position to #{data[:vars][:retry][:orig_body_stream_pos]}", :retry_manager)
100
+ data[:request][:instance].body.pos = data[:vars][:retry][:orig_body_stream_pos]
101
+ end
102
+ end
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,98 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module RightScale
25
+ module CloudApi
26
+
27
+ # This is a parent class for all the other routines.
28
+ #
29
+ # The routine is a very simple object that does a simple task in the API call processing stack
30
+ # and exits. In most cases a single routine knows nothing about any other routines. It just
31
+ # takes incoming params from @data hash, processes it and stores back to the @adata attribute.
32
+ #
33
+ class Routine
34
+ attr_reader :data
35
+
36
+ # Initializes the @data attribute. Is called before *process* method.
37
+ #
38
+ # @param [Hash] data See ApiManager for better explanation what data is.
39
+ #
40
+ def reset(data=nil)
41
+ @data = data
42
+ end
43
+
44
+ # Main entry point. The method must be overriden by sub-classes.
45
+ def process
46
+ raise Error::new("This method should be implemented by a subclass")
47
+ end
48
+
49
+ # Initialize and process the routine. Is usially called from unit tests.
50
+ def execute(data)
51
+ reset(data)
52
+ process
53
+ end
54
+
55
+ # Current options.
56
+ #
57
+ # @return [Hash]
58
+ #
59
+ def options
60
+ @data[:options]
61
+ end
62
+
63
+ # Current logger.
64
+ #
65
+ # @return [CloudApiLogger]
66
+ #
67
+ def cloud_api_logger
68
+ options[:cloud_api_logger]
69
+ end
70
+
71
+ # The method takes a block of code and logs how much time the given block took to execute.
72
+ #
73
+ # @param [String] description The prefix that is added to every logged line.
74
+ # @param [Symbol] log_key The log key (see {RightScale::CloudApi::CloudApiLogger}).
75
+ #
76
+ def with_timer(description = 'Timer', log_key = :timer, &block)
77
+ cloud_api_logger.log("#{description} started...",:timer)
78
+ start = Time::now
79
+ result = block.call
80
+ cloud_api_logger.log("#{description} completed (#{'%.6f' % (Time::now - start)} sec)", log_key)
81
+ result
82
+ end
83
+
84
+ # A helper method for invoking callbacks.
85
+ #
86
+ # The method checks if the given Proc exists and invokes it with the given set of arguments.
87
+ # In the case when proc==nil the method does nothing.
88
+ #
89
+ # @param [Proc] proc The callback.
90
+ # @param [Any] args A set of callback method arguments.
91
+ #
92
+ def invoke_callback_method(proc, *args) # :nodoc:
93
+ proc.call(*args) if proc.is_a?(Proc)
94
+ end
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,72 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'rubygems'
25
+ require 'time'
26
+ require 'openssl'
27
+ require 'net/https'
28
+ require 'base64'
29
+ require 'cgi'
30
+ require 'logger'
31
+ require 'digest/md5'
32
+
33
+ $:.unshift(File::expand_path(File::dirname(__FILE__)))
34
+
35
+ require "right_cloud_api_base_version"
36
+
37
+ # Helpers
38
+ require "base/helpers/support"
39
+ require "base/helpers/support.xml"
40
+ require "base/helpers/utils"
41
+ require "base/helpers/net_http_patch"
42
+ require "base/helpers/http_headers"
43
+ require "base/helpers/http_parent"
44
+ require "base/helpers/http_request"
45
+ require "base/helpers/http_response"
46
+ require "base/helpers/query_api_patterns"
47
+ require "base/helpers/cloud_api_logger"
48
+
49
+ # Managers
50
+ require "base/manager"
51
+ require "base/api_manager"
52
+
53
+ # Default parsers
54
+ require "base/parsers/plain"
55
+ require "base/parsers/json"
56
+ require "base/parsers/rexml"
57
+ require "base/parsers/sax"
58
+
59
+ # Default routines
60
+ require "base/routines/routine"
61
+ require "base/routines/retry_manager"
62
+ require "base/routines/request_initializer"
63
+ require "base/routines/request_generator"
64
+ require "base/routines/connection_proxy"
65
+ require "base/routines/connection_proxies/right_http_connection_proxy"
66
+ require "base/routines/connection_proxies/net_http_persistent_proxy"
67
+ require "base/routines/response_parser"
68
+ require "base/routines/request_analyzer"
69
+ require "base/routines/response_analyzer"
70
+ require "base/routines/cache_validator"
71
+ require "base/routines/result_wrapper"
72
+
@@ -0,0 +1,37 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ # RightScale namespace
25
+ #
26
+ # @api public
27
+ #
28
+ module RightScale
29
+ # CloudApi gem namespace
30
+ module CloudApi
31
+ # CloudApi gem version namespace
32
+ module VERSION
33
+ # The gem version
34
+ STRING = '0.1.0'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,63 @@
1
+ #-- -*- mode: ruby; encoding: utf-8 -*-
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'rubygems'
25
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib/right_cloud_api_base_version'))
26
+
27
+ Gem::Specification.new do |spec|
28
+ spec.name = 'right_cloud_api_base'
29
+ spec.version = RightScale::CloudApi::VERSION::STRING
30
+ spec.authors = ['RightScale, Inc.']
31
+ spec.email = 'support@rightscale.com'
32
+ spec.summary = 'The gem provides base Query and REST API management functionalities for ' +
33
+ 'Amazon, OpenStack, Rackspace, CloudStack, etc cloud services'
34
+ spec.rdoc_options = ['--main', 'README.md', '--title', '']
35
+ spec.extra_rdoc_files = ['README.md']
36
+ spec.require_path = 'lib'
37
+ spec.required_ruby_version = '>= 1.8.7'
38
+
39
+ spec.add_dependency 'json', '>= 1.0.0'
40
+ spec.add_dependency 'ruby-hmac', '>= 0.4.0'
41
+ spec.add_dependency 'libxml-ruby', '>= 1.0.0'
42
+ spec.add_dependency 'net-http-persistent', '>= 2.9.0'
43
+
44
+ spec.add_dependency 'redcarpet', (RUBY_VERSION < '1.9') ? '= 2.3.0' : '>= 3.0.0'
45
+
46
+ spec.add_development_dependency 'rspec', '>= 2.14.0'
47
+ spec.add_development_dependency 'rake'
48
+
49
+ spec.description = <<-EOF
50
+ == DESCRIPTION:
51
+
52
+ right_cloud_api_base gem.
53
+
54
+ The gem provides base Query and REST API management functionalities for
55
+ Amazon, OpenStack, Rackspace, CloudStack, etc cloud services.
56
+
57
+ EOF
58
+
59
+ candidates = Dir.glob('{lib,spec}/**/*') +
60
+ ['LICENSE', 'HISTORY', 'README.md', 'Rakefile', 'right_cloud_api_base.gemspec']
61
+ spec.files = candidates.sort
62
+ spec.test_files = Dir.glob('spec/**/*')
63
+ end