aliyun-ess 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +5 -0
- data/INSTALL +13 -0
- data/bin/ess +6 -0
- data/bin/setup.rb +11 -0
- data/lib/aliyun/ess.rb +33 -0
- data/lib/aliyun/ess/authentication.rb +121 -0
- data/lib/aliyun/ess/base.rb +128 -0
- data/lib/aliyun/ess/collection.rb +24 -0
- data/lib/aliyun/ess/connection.rb +226 -0
- data/lib/aliyun/ess/error.rb +84 -0
- data/lib/aliyun/ess/exceptions.rb +82 -0
- data/lib/aliyun/ess/extensions.rb +174 -0
- data/lib/aliyun/ess/parsing.rb +67 -0
- data/lib/aliyun/ess/response.rb +161 -0
- data/lib/aliyun/ess/scaling_group.rb +50 -0
- data/lib/aliyun/ess/scaling_rule.rb +45 -0
- data/lib/aliyun/ess/service.rb +31 -0
- data/lib/aliyun/ess/version.rb +14 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6220299fa48afc6abb759b80526dac2889b0052c
|
4
|
+
data.tar.gz: 6c6b2757addd2ae6314f5951823c3c16b2f7a2aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ca60cb188e0e809e4169a58d25486f591ef59e8800fb52e0a306961017e7613734d9aa67413a1b95814be5e2c725331d503a75e602cdc19644c34b1810a09785
|
7
|
+
data.tar.gz: af36c635c32689e74a812381008171e674e5d837e653743d2a61f7726355509ea6f07d03f55dd8ec5cbc3510d1de455885861a0895318d50e759d729b6813c9b
|
data/INSTALL
ADDED
data/bin/ess
ADDED
data/bin/setup.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
#!/usr/bin/env ruby
|
3
|
+
if ENV['ACCESS_KEY_ID'] && ENV['SECRET_ACCESS_KEY']
|
4
|
+
Aliyun::ESS::Base.establish_connection!(
|
5
|
+
:access_key_id => ENV['ACCESS_KEY_ID'],
|
6
|
+
:secret_access_key => ENV['SECRET_ACCESS_KEY']
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
#require File.dirname(__FILE__) + '/../test/fixtures'
|
11
|
+
include Aliyun::ESS
|
data/lib/aliyun/ess.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'cgi'
|
3
|
+
require 'uri'
|
4
|
+
require 'openssl'
|
5
|
+
require 'digest/sha1'
|
6
|
+
require 'net/https'
|
7
|
+
require 'time'
|
8
|
+
require 'date'
|
9
|
+
require 'open-uri'
|
10
|
+
require 'yajl/json_gem'
|
11
|
+
require 'rack/utils'
|
12
|
+
require 'byebug'
|
13
|
+
|
14
|
+
$:.unshift(File.dirname(__FILE__))
|
15
|
+
|
16
|
+
require 'ess/version'
|
17
|
+
require 'ess/extensions' unless defined? Aliyun::OSS
|
18
|
+
require 'ess/exceptions'
|
19
|
+
require 'ess/error'
|
20
|
+
require 'ess/authentication'
|
21
|
+
require 'ess/connection'
|
22
|
+
require 'ess/parsing'
|
23
|
+
require 'ess/base'
|
24
|
+
require 'ess/service'
|
25
|
+
require 'ess/collection'
|
26
|
+
require 'ess/scaling_group'
|
27
|
+
require 'ess/scaling_rule'
|
28
|
+
require 'ess/response'
|
29
|
+
|
30
|
+
|
31
|
+
Aliyun::ESS::Base.class_eval do
|
32
|
+
include Aliyun::ESS::Connection::Management
|
33
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Aliyun
|
3
|
+
module ESS
|
4
|
+
class Authentication
|
5
|
+
class Signature < String #:nodoc:
|
6
|
+
attr_reader :params, :access_key_id, :secret_access_key, :options
|
7
|
+
|
8
|
+
def initialize(params, access_key_id, secret_access_key, options = {})
|
9
|
+
super()
|
10
|
+
@params, @access_key_id, @secret_access_key = params, access_key_id, secret_access_key
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def escape_string(str)
|
17
|
+
CGI.escape(str).gsub(/\+/,'%20').gsub(/%7E/, '~')
|
18
|
+
end
|
19
|
+
|
20
|
+
def sign_string
|
21
|
+
StringToSign.new(canonical_string)
|
22
|
+
end
|
23
|
+
|
24
|
+
def canonical_string
|
25
|
+
@canonical_string ||= CanonicalString.new(params, access_key_id, {})
|
26
|
+
end
|
27
|
+
|
28
|
+
def encoded_canonical
|
29
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
30
|
+
b64_hmac = [OpenSSL::HMAC.digest(digest, secret_access_key+'&', sign_string)].pack("m").strip
|
31
|
+
url_encode? ? CGI.escape(b64_hmac) : b64_hmac
|
32
|
+
end
|
33
|
+
|
34
|
+
def url_encode?
|
35
|
+
!@options[:url_encode].nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class QueryString < Signature
|
40
|
+
def initialize(*args)
|
41
|
+
super
|
42
|
+
self << build
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def build
|
48
|
+
"#{canonical_string}&Signature=#{escape_string(encoded_canonical)}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class StringToSign < String
|
53
|
+
attr_reader :canonicalized_query_string
|
54
|
+
def initialize(canonicalized_query_string)
|
55
|
+
super()
|
56
|
+
@canonicalized_query_string = canonicalized_query_string
|
57
|
+
build
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def build
|
63
|
+
self << 'GET'
|
64
|
+
self << '&%2F&'
|
65
|
+
self << escape_string(canonicalized_query_string)
|
66
|
+
end
|
67
|
+
|
68
|
+
def escape_string(str)
|
69
|
+
CGI.escape(str).gsub(/\+/,'%20').gsub(/%7E/, '~')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class CanonicalString < String
|
74
|
+
DEFAULT_PARAMS = {
|
75
|
+
'Format' => 'JSON',
|
76
|
+
'SignatureMethod' => 'HMAC-SHA1',
|
77
|
+
'SignatureVersion' => '1.0',
|
78
|
+
'Version' => '2014-08-28'
|
79
|
+
}
|
80
|
+
|
81
|
+
attr_reader :params, :query
|
82
|
+
|
83
|
+
def initialize(params, access_key_id, options = {})
|
84
|
+
super()
|
85
|
+
@params = params
|
86
|
+
@access_key_id = access_key_id
|
87
|
+
@options = options
|
88
|
+
self << build
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def build
|
94
|
+
initialize_query
|
95
|
+
|
96
|
+
canonicalized_query_string = query.sort_by{|k, _| k}.map do |key, value|
|
97
|
+
value = value.to_s.strip
|
98
|
+
escaped_value = escape_string(value)
|
99
|
+
"#{key}=#{escaped_value}"
|
100
|
+
end.join('&')
|
101
|
+
|
102
|
+
canonicalized_query_string
|
103
|
+
end
|
104
|
+
|
105
|
+
def escape_string(str)
|
106
|
+
CGI.escape(str).gsub(/\+/,'%20').gsub(/%7E/, '~')
|
107
|
+
end
|
108
|
+
|
109
|
+
def initialize_query
|
110
|
+
@query = { 'AccessKeyId' => @access_key_id }
|
111
|
+
@query = params.merge(@query)
|
112
|
+
@query = DEFAULT_PARAMS.merge('SignatureNonce' => random_string, 'Timestamp' => Time.now.utc.iso8601).merge(@query)
|
113
|
+
end
|
114
|
+
|
115
|
+
def random_string(len=32)
|
116
|
+
rand(36**(len-1)..36**(len)).to_s 36
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Aliyun
|
3
|
+
module ESS
|
4
|
+
DEFAULT_HOST = 'ess.aliyuncs.com'
|
5
|
+
class Base
|
6
|
+
class << self
|
7
|
+
# Wraps the current connection's request method and picks the appropriate response class to wrap the response in.
|
8
|
+
# If the response is an error, it will raise that error as an exception. All such exceptions can be caught by rescuing
|
9
|
+
# their superclass, the ResponseError exception class.
|
10
|
+
#
|
11
|
+
# It is unlikely that you would call this method directly. Subclasses of Base have convenience methods for each http request verb
|
12
|
+
# that wrap calls to request.
|
13
|
+
def request(verb, path, params = {}, options = {}, body = nil, attempts = 0, &block)
|
14
|
+
Service.response = nil
|
15
|
+
process_params!(params, verb)
|
16
|
+
response = response_class.new(connection.request(verb, path, params, options, body, attempts, &block))
|
17
|
+
Service.response = response
|
18
|
+
|
19
|
+
Error::Response.new(response.response).error.raise if response.error?
|
20
|
+
response
|
21
|
+
# Once in a while, a request to OSS returns an internal error. A glitch in the matrix I presume. Since these
|
22
|
+
# errors are few and far between the request method will rescue InternalErrors the first three times they encouter them
|
23
|
+
# and will retry the request again. Most of the time the second attempt will work.
|
24
|
+
rescue InternalError, RequestTimeout
|
25
|
+
if attempts == 3
|
26
|
+
raise
|
27
|
+
else
|
28
|
+
attempts += 1
|
29
|
+
retry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
[:get, :post, :put, :delete, :head].each do |verb|
|
34
|
+
class_eval(<<-EVAL, __FILE__, __LINE__)
|
35
|
+
def #{verb}(path, params = {}, headers = {}, body = nil, &block)
|
36
|
+
request(:#{verb}, path, params, headers, body, &block)
|
37
|
+
end
|
38
|
+
EVAL
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def response_class
|
44
|
+
FindResponseClass.for(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
def process_params!(params, verb)
|
48
|
+
params.replace(RequestParams.process(params, verb))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Using the conventions layed out in the <tt>response_class</tt> works for more than 80% of the time.
|
52
|
+
# There are a few edge cases though where we want a given class to wrap its responses in different
|
53
|
+
# response classes depending on which method is being called.
|
54
|
+
def respond_with(klass)
|
55
|
+
eval(<<-EVAL, binding, __FILE__, __LINE__)
|
56
|
+
def new_response_class
|
57
|
+
#{klass}
|
58
|
+
end
|
59
|
+
class << self
|
60
|
+
alias_method :old_response_class, :response_class
|
61
|
+
alias_method :response_class, :new_response_class
|
62
|
+
end
|
63
|
+
EVAL
|
64
|
+
yield
|
65
|
+
ensure
|
66
|
+
# Restore the original version
|
67
|
+
eval(<<-EVAL, binding, __FILE__, __LINE__)
|
68
|
+
class << self
|
69
|
+
alias_method :response_class, :old_response_class
|
70
|
+
end
|
71
|
+
EVAL
|
72
|
+
end
|
73
|
+
|
74
|
+
class RequestParams < Hash #:nodoc:
|
75
|
+
attr_reader :options, :verb
|
76
|
+
|
77
|
+
class << self
|
78
|
+
def process(*args, &block)
|
79
|
+
new(*args, &block).process!
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def initialize(options, verb = :get)
|
84
|
+
@options = options.inject({}) {|h, (k,v)| h[k.to_s.camelize] = v.to_s; h }
|
85
|
+
@verb = verb
|
86
|
+
super()
|
87
|
+
end
|
88
|
+
|
89
|
+
def process!
|
90
|
+
replace(options)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def initialize(attributes = {}) #:nodoc:
|
96
|
+
@attributes = attributes
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
attr_reader :attributes
|
102
|
+
|
103
|
+
def connection
|
104
|
+
self.class.connection
|
105
|
+
end
|
106
|
+
|
107
|
+
def http
|
108
|
+
connection.http
|
109
|
+
end
|
110
|
+
|
111
|
+
def request(*args, &block)
|
112
|
+
self.class.request(*args, &block)
|
113
|
+
end
|
114
|
+
|
115
|
+
def method_missing(method, *args, &block)
|
116
|
+
case
|
117
|
+
when attributes.has_key?(method.to_s)
|
118
|
+
attributes[method.to_s]
|
119
|
+
when attributes.has_key?(method)
|
120
|
+
attributes[method]
|
121
|
+
else
|
122
|
+
super
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Aliyun
|
3
|
+
module ESS
|
4
|
+
class Collection
|
5
|
+
include SelectiveAttributeProxy
|
6
|
+
|
7
|
+
attr_reader :response, :attributes
|
8
|
+
|
9
|
+
def initialize(response)
|
10
|
+
@response = response
|
11
|
+
@attributes = response.parsed.slice(*%W{page_number page_size total_count})
|
12
|
+
end
|
13
|
+
|
14
|
+
def items
|
15
|
+
@items ||= build_items!
|
16
|
+
end
|
17
|
+
|
18
|
+
def build_items!
|
19
|
+
item_class = eval response.class.name.sub(/::Response$/, '')
|
20
|
+
response.items.map{|e| item_class.new e }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Aliyun
|
3
|
+
module ESS
|
4
|
+
class Connection #:nodoc:
|
5
|
+
class << self
|
6
|
+
def connect(options = {})
|
7
|
+
new(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def prepare_path(path)
|
11
|
+
path = path.remove_extended unless path.valid_utf8?
|
12
|
+
URI.escape(path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :access_key_id, :secret_access_key, :http, :options
|
17
|
+
|
18
|
+
# Creates a new connection. Connections make the actual requests to OSS, though these requests are usually
|
19
|
+
# called from subclasses of Base.
|
20
|
+
#
|
21
|
+
# For details on establishing connections, check the Connection::Management::ClassMethods.
|
22
|
+
def initialize(options = {})
|
23
|
+
@options = Options.new(options)
|
24
|
+
connect
|
25
|
+
end
|
26
|
+
|
27
|
+
def request(verb, path, params = {}, headers = {}, body = nil, attempts = 0, &block)
|
28
|
+
body.rewind if body.respond_to?(:rewind) unless attempts.zero?
|
29
|
+
|
30
|
+
requester = Proc.new do
|
31
|
+
path = self.class.prepare_path(path) if attempts.zero? # Only escape the path once
|
32
|
+
params = ::Rack::Utils.parse_nested_query(URI(path).query).merge(params)
|
33
|
+
|
34
|
+
request_uri = "/?"+query_string_authentication(params)
|
35
|
+
|
36
|
+
puts request_uri
|
37
|
+
|
38
|
+
request = request_method(verb).new(request_uri, headers)
|
39
|
+
add_user_agent!(request)
|
40
|
+
|
41
|
+
if body
|
42
|
+
if body.respond_to?(:read)
|
43
|
+
request.body_stream = body
|
44
|
+
else
|
45
|
+
request.body = body
|
46
|
+
end
|
47
|
+
request.content_length = body.respond_to?(:lstat) ? body.stat.size : body.size
|
48
|
+
else
|
49
|
+
request.content_length = 0
|
50
|
+
end
|
51
|
+
http.request(request, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
if persistent?
|
55
|
+
http.start unless http.started?
|
56
|
+
requester.call
|
57
|
+
else
|
58
|
+
http.start(&requester)
|
59
|
+
end
|
60
|
+
rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
|
61
|
+
@http = create_connection
|
62
|
+
attempts == 3 ? raise : (attempts += 1; retry)
|
63
|
+
end
|
64
|
+
|
65
|
+
def persistent?
|
66
|
+
options[:persistent]
|
67
|
+
end
|
68
|
+
|
69
|
+
def protocol(options = {})
|
70
|
+
# This always trumps http.use_ssl?
|
71
|
+
if options[:use_ssl] == false
|
72
|
+
'http://'
|
73
|
+
elsif options[:use_ssl] || http.use_ssl?
|
74
|
+
'https://'
|
75
|
+
else
|
76
|
+
'http://'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
def extract_keys!
|
82
|
+
missing_keys = []
|
83
|
+
extract_key = Proc.new {|key| options[key] || (missing_keys.push(key); nil)}
|
84
|
+
@access_key_id = extract_key[:access_key_id]
|
85
|
+
@secret_access_key = extract_key[:secret_access_key]
|
86
|
+
raise MissingAccessKey.new(missing_keys) unless missing_keys.empty?
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_connection
|
90
|
+
http = Net::HTTP.new(options[:server], options[:port])
|
91
|
+
http.use_ssl = !options[:use_ssl].nil? || options[:port] == 443
|
92
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
93
|
+
http
|
94
|
+
end
|
95
|
+
|
96
|
+
def connect
|
97
|
+
extract_keys!
|
98
|
+
@http = create_connection
|
99
|
+
end
|
100
|
+
|
101
|
+
def port_string
|
102
|
+
default_port = options[:use_ssl] ? 443 : 80
|
103
|
+
http.port == default_port ? '' : ":#{http.port}"
|
104
|
+
end
|
105
|
+
|
106
|
+
# do authentication for now
|
107
|
+
def query_string_authentication(params)
|
108
|
+
Authentication::QueryString.new(params, access_key_id, secret_access_key)
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_user_agent!(request)
|
112
|
+
request['User-Agent'] ||= "Aliyun::ESS/#{Version}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def request_method(verb)
|
116
|
+
Net::HTTP.const_get(verb.to_s.capitalize)
|
117
|
+
end
|
118
|
+
|
119
|
+
def method_missing(method, *args, &block)
|
120
|
+
options[method] || super
|
121
|
+
end
|
122
|
+
|
123
|
+
module Management #:nodoc:
|
124
|
+
def self.included(base)
|
125
|
+
base.cattr_accessor :connections
|
126
|
+
base.connections = {}
|
127
|
+
base.extend ClassMethods
|
128
|
+
end
|
129
|
+
|
130
|
+
# Manage the creation and destruction of connections for Aliyun::OSS::Base and its subclasses. Connections are
|
131
|
+
# created with establish_connection!.
|
132
|
+
module ClassMethods
|
133
|
+
# Creates a new connection with which to make requests to the ESS servers for the calling class.
|
134
|
+
#
|
135
|
+
# Aliyun::ESS::Base.establish_connection!(:access_key_id => '...', :secret_access_key => '...')
|
136
|
+
#
|
137
|
+
# == Required arguments
|
138
|
+
#
|
139
|
+
# * <tt>:access_key_id</tt> - The access key id for your OSS account. Provided by Aliyun.
|
140
|
+
# * <tt>:secret_access_key</tt> - The secret access key for your OSS account. Provided by Aliyun.
|
141
|
+
#
|
142
|
+
# If any of these required arguments is missing, a MissingAccessKey exception will be raised.
|
143
|
+
#
|
144
|
+
# == Optional arguments
|
145
|
+
#
|
146
|
+
# * <tt>:server</tt> - The server to make requests to. You can use this to specify your bucket in the subdomain,
|
147
|
+
# or your own domain's cname if you are using virtual hosted buckets. Defaults to <tt>oss.aliyuncs.com</tt>.
|
148
|
+
# * <tt>:port</tt> - The port to the requests should be made on. Defaults to 80 or 443 if the <tt>:use_ssl</tt>
|
149
|
+
# argument is set.
|
150
|
+
# * <tt>:use_ssl</tt> - Whether requests should be made over SSL. If set to true, the <tt>:port</tt> argument
|
151
|
+
# will be implicitly set to 443, unless specified otherwise. Defaults to false.
|
152
|
+
# * <tt>:persistent</tt> - Whether to use a persistent connection to the server. Having this on provides around a two fold
|
153
|
+
# performance increase but for long running processes some firewalls may find the long lived connection suspicious and close the connection.
|
154
|
+
# If you run into connection errors, try setting <tt>:persistent</tt> to false. Defaults to false.
|
155
|
+
def establish_connection!(options = {})
|
156
|
+
# After you've already established the default connection, just specify
|
157
|
+
# the difference for subsequent connections
|
158
|
+
options = default_connection.options.merge(options) if connected?
|
159
|
+
connections[connection_name] = Connection.connect(options)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns the connection for the current class, or Base's default connection if the current class does not
|
163
|
+
# have its own connection.
|
164
|
+
#
|
165
|
+
# If not connection has been established yet, NoConnectionEstablished will be raised.
|
166
|
+
def connection
|
167
|
+
if connected?
|
168
|
+
connections[connection_name] || default_connection
|
169
|
+
else
|
170
|
+
raise NoConnectionEstablished
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns true if a connection has been made yet.
|
175
|
+
def connected?
|
176
|
+
!connections.empty?
|
177
|
+
end
|
178
|
+
|
179
|
+
# Removes the connection for the current class. If there is no connection for the current class, the default
|
180
|
+
# connection will be removed.
|
181
|
+
def disconnect(name = connection_name)
|
182
|
+
name = default_connection unless connections.has_key?(name)
|
183
|
+
connection = connections[name]
|
184
|
+
connection.http.finish if connection.persistent?
|
185
|
+
connections.delete(name)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Clears *all* connections, from all classes, with prejudice.
|
189
|
+
def disconnect!
|
190
|
+
connections.each_key {|connection| disconnect(connection)}
|
191
|
+
end
|
192
|
+
|
193
|
+
private
|
194
|
+
def connection_name
|
195
|
+
name
|
196
|
+
end
|
197
|
+
|
198
|
+
def default_connection_name
|
199
|
+
'Aliyun::ESS::Base'
|
200
|
+
end
|
201
|
+
|
202
|
+
def default_connection
|
203
|
+
connections[default_connection_name]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
class Options < Hash #:nodoc:
|
209
|
+
VALID_OPTIONS = [:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent].freeze
|
210
|
+
|
211
|
+
def initialize(options = {})
|
212
|
+
super()
|
213
|
+
validate(options)
|
214
|
+
replace(:server => DEFAULT_HOST, :port => (options[:use_ssl] ? 443 : 80))
|
215
|
+
merge!(options)
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
def validate(options)
|
220
|
+
invalid_options = options.keys - VALID_OPTIONS
|
221
|
+
raise InvalidConnectionOption.new(invalid_options) unless invalid_options.empty?
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|