fog-core 1.21.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 +15 -0
- data/lib/fog/account.rb +25 -0
- data/lib/fog/billing.rb +23 -0
- data/lib/fog/cdn.rb +23 -0
- data/lib/fog/compute.rb +80 -0
- data/lib/fog/compute/models/server.rb +104 -0
- data/lib/fog/core.rb +51 -0
- data/lib/fog/core/attributes.rb +227 -0
- data/lib/fog/core/class_from_string.rb +26 -0
- data/lib/fog/core/collection.rb +161 -0
- data/lib/fog/core/connection.rb +72 -0
- data/lib/fog/core/credentials.rb +70 -0
- data/lib/fog/core/current_machine.rb +34 -0
- data/lib/fog/core/deprecated_connection_accessors.rb +41 -0
- data/lib/fog/core/deprecation.rb +23 -0
- data/lib/fog/core/errors.rb +118 -0
- data/lib/fog/core/hmac.rb +35 -0
- data/lib/fog/core/logger.rb +44 -0
- data/lib/fog/core/mock.rb +115 -0
- data/lib/fog/core/model.rb +80 -0
- data/lib/fog/core/provider.rb +34 -0
- data/lib/fog/core/scp.rb +96 -0
- data/lib/fog/core/service.rb +223 -0
- data/lib/fog/core/ssh.rb +137 -0
- data/lib/fog/core/time.rb +32 -0
- data/lib/fog/core/uuid.rb +23 -0
- data/lib/fog/core/wait_for.rb +15 -0
- data/lib/fog/core/wait_for_defaults.rb +21 -0
- data/lib/fog/dns.rb +40 -0
- data/lib/fog/identity.rb +28 -0
- data/lib/fog/image.rb +23 -0
- data/lib/fog/metering.rb +25 -0
- data/lib/fog/monitoring.rb +24 -0
- data/lib/fog/network.rb +28 -0
- data/lib/fog/orchestration.rb +25 -0
- data/lib/fog/schema/data_validator.rb +154 -0
- data/lib/fog/storage.rb +80 -0
- data/lib/fog/support.rb +26 -0
- data/lib/fog/test_helpers.rb +12 -0
- data/lib/fog/test_helpers/collection_helper.rb +102 -0
- data/lib/fog/test_helpers/compute/flavors_helper.rb +34 -0
- data/lib/fog/test_helpers/compute/server_helper.rb +27 -0
- data/lib/fog/test_helpers/compute/servers_helper.rb +12 -0
- data/lib/fog/test_helpers/formats_helper.rb +99 -0
- data/lib/fog/test_helpers/helper.rb +25 -0
- data/lib/fog/test_helpers/mock_helper.rb +107 -0
- data/lib/fog/test_helpers/model_helper.rb +35 -0
- data/lib/fog/test_helpers/responds_to_helper.rb +13 -0
- data/lib/fog/test_helpers/succeeds_helper.rb +11 -0
- data/lib/fog/version.rb +3 -0
- data/lib/fog/volume.rb +25 -0
- data/lib/fog/vpn.rb +25 -0
- data/lib/tasks/test_task.rb +46 -0
- metadata +267 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
module Fog
|
2
|
+
class HMAC
|
3
|
+
|
4
|
+
def initialize(type, key)
|
5
|
+
@key = key
|
6
|
+
case type
|
7
|
+
when 'sha1'
|
8
|
+
setup_sha1
|
9
|
+
when 'sha256'
|
10
|
+
setup_sha256
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def sign(data)
|
15
|
+
@signer.call(data)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def setup_sha1
|
21
|
+
@digest = OpenSSL::Digest.new('sha1')
|
22
|
+
@signer = lambda do |data|
|
23
|
+
OpenSSL::HMAC.digest(@digest, @key, data)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_sha256
|
28
|
+
@digest = OpenSSL::Digest.new('sha256')
|
29
|
+
@signer = lambda do |data|
|
30
|
+
OpenSSL::HMAC.digest(@digest, @key, data)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Fog
|
2
|
+
class Logger
|
3
|
+
|
4
|
+
@channels = {
|
5
|
+
:deprecation => ::STDERR,
|
6
|
+
:warning => ::STDERR
|
7
|
+
}
|
8
|
+
|
9
|
+
@channels[:debug] = ::STDERR if ENV['DEBUG']
|
10
|
+
|
11
|
+
def self.[](channel)
|
12
|
+
@channels[channel]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.[]=(channel, value)
|
16
|
+
@channels[channel] = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.debug(message)
|
20
|
+
self.write(:debug, "[light_black][fog][DEBUG] #{message}[/]\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.deprecation(message)
|
24
|
+
self.write(:deprecation, "[yellow][fog][DEPRECATION] #{message}[/]\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.warning(message)
|
28
|
+
self.write(:warning, "[yellow][fog][WARNING] #{message}[/]\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.write(key, value)
|
32
|
+
if channel = @channels[key]
|
33
|
+
message = if channel.tty?
|
34
|
+
value.gsub(Formatador::PARSE_REGEX) { "\e[#{Formatador::STYLES[$1.to_sym]}m" }.gsub(Formatador::INDENT_REGEX, '')
|
35
|
+
else
|
36
|
+
value.gsub(Formatador::PARSE_REGEX, '').gsub(Formatador::INDENT_REGEX, '')
|
37
|
+
end
|
38
|
+
channel.write(message)
|
39
|
+
end
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Fog
|
2
|
+
|
3
|
+
@mocking = false
|
4
|
+
|
5
|
+
def self.mock!
|
6
|
+
@mocking = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.unmock!
|
10
|
+
@mocking = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.mock?
|
14
|
+
@mocking
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.mocking?
|
18
|
+
@mocking
|
19
|
+
end
|
20
|
+
|
21
|
+
module Mock
|
22
|
+
|
23
|
+
@delay = 1
|
24
|
+
def self.delay
|
25
|
+
@delay
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.delay=(new_delay)
|
29
|
+
raise ArgumentError, "delay must be non-negative" unless new_delay >= 0
|
30
|
+
@delay = new_delay
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.not_implemented(message = 'Contributions welcome!')
|
34
|
+
raise Fog::Errors::MockNotImplemented.new(message)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.random_ip(opts = {:version => :v4})
|
38
|
+
version = opts[:version]
|
39
|
+
if version == :v6
|
40
|
+
bit_length = 128
|
41
|
+
family = Socket::AF_INET6
|
42
|
+
elsif version == :v4
|
43
|
+
bit_length = 32
|
44
|
+
family = Socket::AF_INET
|
45
|
+
else
|
46
|
+
raise ArgumentError, "Unknown IP version: #{version}"
|
47
|
+
end
|
48
|
+
|
49
|
+
seed = 1 + rand((2**bit_length)-1)
|
50
|
+
IPAddr.new(seed, family).to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.random_base64(length)
|
54
|
+
random_selection(
|
55
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
|
56
|
+
length
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.random_hex(length)
|
61
|
+
max = ('f' * length).to_i(16)
|
62
|
+
rand(max).to_s(16).rjust(length, '0')
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.random_letters(length)
|
66
|
+
random_selection(
|
67
|
+
'abcdefghijklmnopqrstuvwxyz',
|
68
|
+
length
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.random_numbers(length)
|
73
|
+
max = ('9' * length).to_i
|
74
|
+
rand(max).to_s
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.random_letters_and_numbers(length)
|
78
|
+
random_selection(
|
79
|
+
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
|
80
|
+
length
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.random_selection(characters, length)
|
85
|
+
selection = ''
|
86
|
+
length.times do
|
87
|
+
position = rand(characters.length)
|
88
|
+
selection << characters[position..position]
|
89
|
+
end
|
90
|
+
selection
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.reset
|
94
|
+
mocked_services = []
|
95
|
+
Fog.constants.map do |x|
|
96
|
+
x_const = Fog.const_get(x)
|
97
|
+
x_const.respond_to?(:constants) && x_const.constants.map do |y|
|
98
|
+
y_const = x_const.const_get(y)
|
99
|
+
y_const.respond_to?(:constants) && y_const.constants.map do |z|
|
100
|
+
if z.to_sym == :Mock
|
101
|
+
mocked_services << y_const.const_get(z)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
for mocked_service in mocked_services
|
108
|
+
next unless mocked_service.respond_to?(:reset)
|
109
|
+
mocked_service.reset
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require "fog/core/deprecated_connection_accessors"
|
2
|
+
|
3
|
+
module Fog
|
4
|
+
class Model
|
5
|
+
|
6
|
+
extend Fog::Attributes::ClassMethods
|
7
|
+
include Fog::Attributes::InstanceMethods
|
8
|
+
include Fog::Core::DeprecatedConnectionAccessors
|
9
|
+
|
10
|
+
attr_accessor :collection
|
11
|
+
attr_reader :service
|
12
|
+
|
13
|
+
def initialize(new_attributes = {})
|
14
|
+
# TODO Remove compatibility with old connection option
|
15
|
+
@service = new_attributes.delete(:service)
|
16
|
+
if @service.nil? && new_attributes[:connection]
|
17
|
+
Fog::Logger.deprecation("Passing :connection option is deprecated, use :service instead [light_black](#{caller.first})[/]")
|
18
|
+
@service = new_attributes[:connection]
|
19
|
+
end
|
20
|
+
merge_attributes(new_attributes)
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
Thread.current[:formatador] ||= Formatador.new
|
25
|
+
data = "#{Thread.current[:formatador].indentation}<#{self.class.name}"
|
26
|
+
Thread.current[:formatador].indent do
|
27
|
+
unless self.class.attributes.empty?
|
28
|
+
data << "\n#{Thread.current[:formatador].indentation}"
|
29
|
+
data << self.class.attributes.map {|attribute| "#{attribute}=#{send(attribute).inspect}"}.join(",\n#{Thread.current[:formatador].indentation}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
data << "\n#{Thread.current[:formatador].indentation}>"
|
33
|
+
data
|
34
|
+
end
|
35
|
+
|
36
|
+
def reload
|
37
|
+
requires :identity
|
38
|
+
|
39
|
+
return unless data = begin
|
40
|
+
collection.get(identity)
|
41
|
+
rescue Excon::Errors::SocketError
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
new_attributes = data.attributes
|
46
|
+
merge_attributes(new_attributes)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_json(options = {})
|
51
|
+
Fog::JSON.encode(attributes)
|
52
|
+
end
|
53
|
+
|
54
|
+
def symbolize_keys(hash)
|
55
|
+
return nil if hash.nil?
|
56
|
+
hash.inject({}) do |options, (key, value)|
|
57
|
+
options[(key.to_sym rescue key) || key] = value
|
58
|
+
options
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def wait_for(timeout=Fog.timeout, interval=1, &block)
|
63
|
+
reload_has_succeeded = false
|
64
|
+
duration = Fog.wait_for(timeout, interval) do # Note that duration = false if it times out
|
65
|
+
if reload
|
66
|
+
reload_has_succeeded = true
|
67
|
+
instance_eval(&block)
|
68
|
+
else
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
if reload_has_succeeded
|
73
|
+
return duration # false if timeout; otherwise {:duration => elapsed time }
|
74
|
+
else
|
75
|
+
raise Fog::Errors::Error.new("Reload failed, #{self.class} #{self.identity} not present.")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Fog
|
2
|
+
|
3
|
+
def self.providers
|
4
|
+
@providers ||= {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.providers=(new_providers)
|
8
|
+
@providers = new_providers
|
9
|
+
end
|
10
|
+
|
11
|
+
module Provider
|
12
|
+
|
13
|
+
def self.extended(base)
|
14
|
+
provider = base.to_s.split('::').last
|
15
|
+
Fog.providers[provider.downcase.to_sym] = provider
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](service_key)
|
19
|
+
eval(@services_registry[service_key]).new
|
20
|
+
end
|
21
|
+
|
22
|
+
def service(new_service, constant_string)
|
23
|
+
Fog.services[new_service] ||= []
|
24
|
+
Fog.services[new_service] |= [self.to_s.split('::').last.downcase.to_sym]
|
25
|
+
@services_registry ||= {}
|
26
|
+
@services_registry[new_service] = [self.to_s, constant_string].join('::')
|
27
|
+
end
|
28
|
+
|
29
|
+
def services
|
30
|
+
@services_registry.keys
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/fog/core/scp.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module Fog
|
2
|
+
module SCP
|
3
|
+
|
4
|
+
def self.new(address, username, options = {})
|
5
|
+
if Fog.mocking?
|
6
|
+
Fog::SCP::Mock.new(address, username, options)
|
7
|
+
else
|
8
|
+
Fog::SCP::Real.new(address, username, options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Mock
|
13
|
+
|
14
|
+
def self.data
|
15
|
+
@data ||= Hash.new do |hash, key|
|
16
|
+
hash[key] = []
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(address, username, options)
|
21
|
+
@address = address
|
22
|
+
@username = username
|
23
|
+
@options = options
|
24
|
+
end
|
25
|
+
|
26
|
+
def upload(local_path, remote_path, upload_options = {})
|
27
|
+
self.class.data[@address] << { :username => @username,
|
28
|
+
:options => @options,
|
29
|
+
:local_path => local_path,
|
30
|
+
:remote_path => remote_path,
|
31
|
+
:upload_options => upload_options }
|
32
|
+
end
|
33
|
+
|
34
|
+
def download(remote_path, local_path, download_options = {})
|
35
|
+
self.class.data[@address] << { :username => @username,
|
36
|
+
:options => @options,
|
37
|
+
:remote_path => remote_path,
|
38
|
+
:local_path => local_path,
|
39
|
+
:download_options => download_options }
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class Real
|
45
|
+
|
46
|
+
def initialize(address, username, options)
|
47
|
+
require 'net/scp'
|
48
|
+
|
49
|
+
key_manager = Net::SSH::Authentication::KeyManager.new(nil, options)
|
50
|
+
|
51
|
+
unless options[:key_data] || options[:keys] || options[:password] || key_manager.agent
|
52
|
+
raise ArgumentError.new(':key_data, :keys, :password or a loaded ssh-agent is required to initialize SSH')
|
53
|
+
end
|
54
|
+
|
55
|
+
options[:timeout] = 30
|
56
|
+
if options[:key_data] || options[:keys]
|
57
|
+
options[:keys_only] = true
|
58
|
+
#Explicitly set these so net-ssh doesn't add the default keys
|
59
|
+
#as seen at https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/authentication/session.rb#L131-146
|
60
|
+
options[:keys] = [] unless options[:keys]
|
61
|
+
options[:key_data] = [] unless options[:key_data]
|
62
|
+
end
|
63
|
+
|
64
|
+
@address = address
|
65
|
+
@username = username
|
66
|
+
@options = { :paranoid => false }.merge(options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def upload(local_path, remote_path, upload_options = {}, &block)
|
70
|
+
begin
|
71
|
+
Net::SCP.start(@address, @username, @options) do |scp|
|
72
|
+
scp.upload!(local_path, remote_path, upload_options) do |ch, name, sent, total|
|
73
|
+
block.call(ch, name, sent, total) if block
|
74
|
+
end
|
75
|
+
end
|
76
|
+
rescue Exception => error
|
77
|
+
raise error
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def download(remote_path, local_path, download_options = {}, &block)
|
82
|
+
begin
|
83
|
+
Net::SCP.start(@address, @username, @options) do |scp|
|
84
|
+
scp.download!(remote_path, local_path, download_options) do |ch, name, sent, total|
|
85
|
+
block.call(ch, name, sent, total) if block
|
86
|
+
end
|
87
|
+
end
|
88
|
+
rescue Exception => error
|
89
|
+
raise error
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
module Fog
|
2
|
+
|
3
|
+
def self.services
|
4
|
+
@services ||= {}
|
5
|
+
end
|
6
|
+
|
7
|
+
class Service
|
8
|
+
|
9
|
+
class Error < Fog::Errors::Error; end
|
10
|
+
class NotFound < Fog::Errors::NotFound; end
|
11
|
+
|
12
|
+
module NoLeakInspector
|
13
|
+
def inspect
|
14
|
+
"#<#{self.class}:#{self.object_id} #{(self.instance_variables - service.secrets).map {|iv| [iv, self.instance_variable_get(iv).inspect].join('=')}.join(' ')}>"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Collections
|
19
|
+
|
20
|
+
def collections
|
21
|
+
service.collections
|
22
|
+
end
|
23
|
+
|
24
|
+
def mocked_requests
|
25
|
+
service.mocked_requests
|
26
|
+
end
|
27
|
+
|
28
|
+
def requests
|
29
|
+
service.requests
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
|
36
|
+
def inherited(child)
|
37
|
+
child.class_eval <<-EOS, __FILE__, __LINE__
|
38
|
+
class Error < Fog::Service::Error; end
|
39
|
+
class NotFound < Fog::Service::NotFound; end
|
40
|
+
|
41
|
+
module Collections
|
42
|
+
include Fog::Service::Collections
|
43
|
+
|
44
|
+
def service
|
45
|
+
#{child}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.service
|
50
|
+
#{child}
|
51
|
+
end
|
52
|
+
EOS
|
53
|
+
end
|
54
|
+
|
55
|
+
def new(options={})
|
56
|
+
options = Fog.symbolize_credentials(options)
|
57
|
+
options = fetch_credentials(options).merge(options)
|
58
|
+
validate_options(options)
|
59
|
+
coerce_options(options)
|
60
|
+
setup_requirements
|
61
|
+
|
62
|
+
if Fog.mocking?
|
63
|
+
service::Mock.send(:include, service::Collections)
|
64
|
+
service::Mock.new(options)
|
65
|
+
else
|
66
|
+
service::Real.send(:include, service::Collections)
|
67
|
+
service::Real.send(:include, service::NoLeakInspector)
|
68
|
+
service::Real.new(options)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def fetch_credentials(options)
|
73
|
+
# attempt to load credentials from config file
|
74
|
+
begin
|
75
|
+
Fog.credentials.reject {|key, value| !(recognized | requirements).include?(key)}
|
76
|
+
rescue LoadError
|
77
|
+
# if there are no configured credentials, do nothing
|
78
|
+
{}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def setup_requirements
|
83
|
+
if superclass.respond_to?(:setup_requirements)
|
84
|
+
superclass.setup_requirements
|
85
|
+
end
|
86
|
+
|
87
|
+
@required ||= false
|
88
|
+
unless @required
|
89
|
+
for collection in collections
|
90
|
+
require [@model_path, collection].join('/')
|
91
|
+
constant = collection.to_s.split('_').map {|characters| characters[0...1].upcase << characters[1..-1]}.join('')
|
92
|
+
service::Collections.module_eval <<-EOS, __FILE__, __LINE__
|
93
|
+
def #{collection}(attributes = {})
|
94
|
+
#{service}::#{constant}.new({:service => self}.merge(attributes))
|
95
|
+
end
|
96
|
+
EOS
|
97
|
+
end
|
98
|
+
for model in models
|
99
|
+
require [@model_path, model].join('/')
|
100
|
+
end
|
101
|
+
for request in requests
|
102
|
+
require [@request_path, request].join('/')
|
103
|
+
if service::Mock.method_defined?(request)
|
104
|
+
mocked_requests << request
|
105
|
+
else
|
106
|
+
service::Mock.module_eval <<-EOS, __FILE__, __LINE__
|
107
|
+
def #{request}(*args)
|
108
|
+
Fog::Mock.not_implemented
|
109
|
+
end
|
110
|
+
EOS
|
111
|
+
end
|
112
|
+
end
|
113
|
+
@required = true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def model_path(new_path)
|
118
|
+
@model_path = new_path
|
119
|
+
end
|
120
|
+
|
121
|
+
def collection(new_collection)
|
122
|
+
collections << new_collection
|
123
|
+
end
|
124
|
+
|
125
|
+
def collections
|
126
|
+
@collections ||= []
|
127
|
+
end
|
128
|
+
|
129
|
+
def coerce_options(options)
|
130
|
+
options.each do |key, value|
|
131
|
+
value_string = value.to_s.downcase
|
132
|
+
if value.nil?
|
133
|
+
options.delete(key)
|
134
|
+
elsif value == value_string.to_i.to_s
|
135
|
+
options[key] = value.to_i
|
136
|
+
else
|
137
|
+
options[key] = case value_string
|
138
|
+
when 'false'
|
139
|
+
false
|
140
|
+
when 'true'
|
141
|
+
true
|
142
|
+
else
|
143
|
+
value
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def mocked_requests
|
150
|
+
@mocked_requests ||= []
|
151
|
+
end
|
152
|
+
|
153
|
+
def model(new_model)
|
154
|
+
models << new_model
|
155
|
+
end
|
156
|
+
|
157
|
+
def models
|
158
|
+
@models ||= []
|
159
|
+
end
|
160
|
+
|
161
|
+
def request_path(new_path)
|
162
|
+
@request_path = new_path
|
163
|
+
end
|
164
|
+
|
165
|
+
def request(new_request)
|
166
|
+
requests << new_request
|
167
|
+
end
|
168
|
+
|
169
|
+
def requests
|
170
|
+
@requests ||= []
|
171
|
+
end
|
172
|
+
|
173
|
+
def secrets(*args)
|
174
|
+
if args.empty?
|
175
|
+
@secrets ||= []
|
176
|
+
else
|
177
|
+
args.inject(secrets) do |secrets, secret|
|
178
|
+
secrets << "@#{secret}".to_sym
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def requires(*args)
|
184
|
+
requirements.concat(args)
|
185
|
+
end
|
186
|
+
|
187
|
+
def requirements
|
188
|
+
@requirements ||= []
|
189
|
+
end
|
190
|
+
|
191
|
+
def recognizes(*args)
|
192
|
+
recognized.concat(args)
|
193
|
+
end
|
194
|
+
|
195
|
+
def recognized
|
196
|
+
@recognized ||= [:connection_options]
|
197
|
+
end
|
198
|
+
|
199
|
+
def validate_options(options)
|
200
|
+
keys = []
|
201
|
+
for key, value in options
|
202
|
+
unless value.nil?
|
203
|
+
keys << key
|
204
|
+
end
|
205
|
+
end
|
206
|
+
missing = requirements - keys
|
207
|
+
unless missing.empty?
|
208
|
+
raise ArgumentError, "Missing required arguments: #{missing.join(', ')}"
|
209
|
+
end
|
210
|
+
|
211
|
+
unless recognizes.empty?
|
212
|
+
unrecognized = options.keys - requirements - recognized
|
213
|
+
unless unrecognized.empty?
|
214
|
+
Fog::Logger.warning("Unrecognized arguments: #{unrecognized.join(', ')}")
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|