aliyun-ess 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|