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
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OTE4YzMxODZiYTk3ZTk1ZmRkMTQyZjliNzBhYTcyYTdjZWY3M2U4OQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OWIyMTkzMTU0NjkzNzkyMGUxYzFhM2MzZDY3MzkwOTNlNzFlYjNhNw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MGIxYTNmNzA1YmRhNDZmYTllNjk5Zjk4YTdlMDRlZmE5ZGM2ZmRhMDllZGMz
|
10
|
+
YzRmOTQzYzEyMDFlNDk1MTQ4YmQ0OTQ4NDljZmViNmI0YjY3N2Q1M2E5ZDA2
|
11
|
+
MGM0OWMxYTNhMzQ1NmNmODcwMjYyZDQyNWRjZDY4ZDhkN2EzMzg=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MDBhMWUxZDRkZjA5Yzg2ZTIzNjMyNDBlMWViMTkwMDBlMjZlM2M4NDYxNjAy
|
14
|
+
NGM5OWYzMzhhN2JlOWQ1YzZlODYyMzg4NTkzYzg0NGUxOGRhMWIxMzhhZTc0
|
15
|
+
ZDYxMmFjY2ZhMDY0NDM1YjNmNWEzN2NlYTcyNDVhMGZmNzY1NTc=
|
data/lib/fog/account.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Fog
|
2
|
+
module Account
|
3
|
+
|
4
|
+
def self.[](provider)
|
5
|
+
self.new(:provider => provider)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.new(attributes)
|
9
|
+
attributes = attributes.dup
|
10
|
+
provider = attributes.delete(:provider).to_s.downcase.to_sym
|
11
|
+
|
12
|
+
if provider == :stormondemand
|
13
|
+
require 'fog/storm_on_demand/account'
|
14
|
+
Fog::Account::StormOnDemand.new(attributes)
|
15
|
+
else
|
16
|
+
raise ArgumentError.new("#{provider} has no account service")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.providers
|
21
|
+
Fog.services[:account]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/fog/billing.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Fog
|
2
|
+
module Billing
|
3
|
+
|
4
|
+
def self.[](provider)
|
5
|
+
self.new(:provider => provider)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.new(attributes)
|
9
|
+
attributes = attributes.dup
|
10
|
+
provider = attributes.delete(:provider).to_s.downcase.to_sym
|
11
|
+
if provider == :stormondemand
|
12
|
+
require 'fog/storm_on_demand/billing'
|
13
|
+
Fog::Billing::StormOnDemand.new(attributes)
|
14
|
+
else
|
15
|
+
raise ArgumentError.new("#{provider} has no billing service")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.providers
|
20
|
+
Fog.services[:billing]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/fog/cdn.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Fog
|
2
|
+
module CDN
|
3
|
+
|
4
|
+
def self.[](provider)
|
5
|
+
self.new(:provider => provider)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.new(attributes)
|
9
|
+
attributes = attributes.dup # prevent delete from having side effects
|
10
|
+
provider = attributes.delete(:provider).to_s.downcase.to_sym
|
11
|
+
if self.providers.include?(provider)
|
12
|
+
require "fog/#{provider}/cdn"
|
13
|
+
return Fog::CDN.const_get(Fog.providers[provider]).new(attributes)
|
14
|
+
end
|
15
|
+
raise ArgumentError.new("#{provider} is not a recognized cdn provider")
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.providers
|
19
|
+
Fog.services[:cdn]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/fog/compute.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
|
4
|
+
def self.[](provider)
|
5
|
+
self.new(:provider => provider)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.new(attributes)
|
9
|
+
attributes = attributes.dup # prevent delete from having side effects
|
10
|
+
provider = attributes.delete(:provider).to_s.downcase.to_sym
|
11
|
+
|
12
|
+
|
13
|
+
case provider
|
14
|
+
when :gogrid
|
15
|
+
require 'fog/go_grid/compute'
|
16
|
+
Fog::Compute::GoGrid.new(attributes)
|
17
|
+
when :hp
|
18
|
+
version = attributes.delete(:version)
|
19
|
+
version = version.to_s.downcase.to_sym unless version.nil?
|
20
|
+
if version == :v2
|
21
|
+
require 'fog/hp/compute_v2'
|
22
|
+
Fog::Compute::HPV2.new(attributes)
|
23
|
+
else
|
24
|
+
Fog::Logger.deprecation "HP Cloud Compute V1 service will be soon deprecated. Please use `:version => v2` attribute to use HP Cloud Compute V2 service."
|
25
|
+
require 'fog/hp/compute'
|
26
|
+
Fog::Compute::HP.new(attributes)
|
27
|
+
end
|
28
|
+
when :new_servers
|
29
|
+
require 'fog/bare_metal_cloud/compute'
|
30
|
+
Fog::Logger.deprecation "`new_servers` is deprecated. Please use `bare_metal_cloud` instead."
|
31
|
+
Fog::Compute::BareMetalCloud.new(attributes)
|
32
|
+
when :baremetalcloud
|
33
|
+
require 'fog/bare_metal_cloud/compute'
|
34
|
+
Fog::Compute::BareMetalCloud.new(attributes)
|
35
|
+
when :rackspace
|
36
|
+
version = attributes.delete(:version)
|
37
|
+
version = version.to_s.downcase.to_sym unless version.nil?
|
38
|
+
if version == :v1
|
39
|
+
Fog::Logger.deprecation "First Gen Cloud Servers are deprecated. Please use `:version => :v2` attribute to use Next Gen Cloud Servers."
|
40
|
+
require 'fog/rackspace/compute'
|
41
|
+
Fog::Compute::Rackspace.new(attributes)
|
42
|
+
else
|
43
|
+
require 'fog/rackspace/compute_v2'
|
44
|
+
Fog::Compute::RackspaceV2.new(attributes)
|
45
|
+
end
|
46
|
+
when :stormondemand
|
47
|
+
require 'fog/storm_on_demand/compute'
|
48
|
+
Fog::Compute::StormOnDemand.new(attributes)
|
49
|
+
when :vcloud
|
50
|
+
require 'fog/vcloud/compute'
|
51
|
+
Fog::Vcloud::Compute.new(attributes)
|
52
|
+
when :vclouddirector
|
53
|
+
require 'fog/vcloud_director/compute'
|
54
|
+
Fog::Compute::VcloudDirector.new(attributes)
|
55
|
+
else
|
56
|
+
if self.providers.include?(provider)
|
57
|
+
require "fog/#{provider}/compute"
|
58
|
+
return Fog::Compute.const_get(Fog.providers[provider]).new(attributes)
|
59
|
+
end
|
60
|
+
raise ArgumentError.new("#{provider} is not a recognized compute provider")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.providers
|
65
|
+
Fog.services[:compute]
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.servers
|
69
|
+
servers = []
|
70
|
+
for provider in self.providers
|
71
|
+
begin
|
72
|
+
servers.concat(self[provider].servers)
|
73
|
+
rescue # ignore any missing credentials/etc
|
74
|
+
end
|
75
|
+
end
|
76
|
+
servers
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'fog/core/model'
|
2
|
+
|
3
|
+
module Fog
|
4
|
+
module Compute
|
5
|
+
class Server < Fog::Model
|
6
|
+
|
7
|
+
attr_writer :username, :private_key, :private_key_path, :public_key, :public_key_path, :ssh_port, :ssh_options
|
8
|
+
|
9
|
+
def username
|
10
|
+
@username ||= 'root'
|
11
|
+
end
|
12
|
+
|
13
|
+
def private_key_path
|
14
|
+
@private_key_path ||= Fog.credentials[:private_key_path]
|
15
|
+
@private_key_path &&= File.expand_path(@private_key_path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def private_key
|
19
|
+
@private_key ||= private_key_path && File.read(private_key_path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def public_key_path
|
23
|
+
@public_key_path ||= Fog.credentials[:public_key_path]
|
24
|
+
@public_key_path &&= File.expand_path(@public_key_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def public_key
|
28
|
+
@public_key ||= public_key_path && File.read(public_key_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Port used for ssh/scp interactions with server.
|
32
|
+
# @return [Integer] IP port
|
33
|
+
# @note By default this returns 22
|
34
|
+
def ssh_port
|
35
|
+
@ssh_port ||= 22
|
36
|
+
end
|
37
|
+
|
38
|
+
# Sets the proc used to determine the IP Address used for ssh/scp interactions.
|
39
|
+
# @example
|
40
|
+
# service.servers.bootstrap :name => 'bootstrap-server',
|
41
|
+
# :flavor_id => service.flavors.first.id,
|
42
|
+
# :image_id => service.images.find {|img| img.name =~ /Ubuntu/}.id,
|
43
|
+
# :public_key_path => '~/.ssh/fog_rsa.pub',
|
44
|
+
# :private_key_path => '~/.ssh/fog_rsa',
|
45
|
+
# :ssh_ip_address => Proc.new {|server| server.private_ip_address }
|
46
|
+
#
|
47
|
+
# @note By default scp/ssh will use the public_ip_address if this proc is not set.
|
48
|
+
def ssh_ip_address=(proc)
|
49
|
+
@ssh_ip_address = proc
|
50
|
+
end
|
51
|
+
|
52
|
+
# IP Address used for ssh/scp interactions with server.
|
53
|
+
# @return [String] IP Address
|
54
|
+
# @note By default this returns the public_ip_address
|
55
|
+
def ssh_ip_address
|
56
|
+
return public_ip_address unless @ssh_ip_address
|
57
|
+
return @ssh_ip_address.call(self) if @ssh_ip_address.is_a?(Proc)
|
58
|
+
@ssh_ip_address
|
59
|
+
end
|
60
|
+
|
61
|
+
def ssh_options
|
62
|
+
@ssh_options ||= {}
|
63
|
+
ssh_options = @ssh_options.merge({:port => ssh_port})
|
64
|
+
if private_key
|
65
|
+
ssh_options[:key_data] = [private_key]
|
66
|
+
ssh_options[:auth_methods] = ["publickey"]
|
67
|
+
end
|
68
|
+
ssh_options
|
69
|
+
end
|
70
|
+
|
71
|
+
def scp(local_path, remote_path, upload_options = {})
|
72
|
+
require 'net/scp'
|
73
|
+
requires :ssh_ip_address, :username
|
74
|
+
|
75
|
+
Fog::SCP.new(ssh_ip_address, username, ssh_options).upload(local_path, remote_path, upload_options)
|
76
|
+
end
|
77
|
+
|
78
|
+
alias_method :scp_upload, :scp
|
79
|
+
|
80
|
+
def scp_download(remote_path, local_path, download_options = {})
|
81
|
+
require 'net/scp'
|
82
|
+
requires :ssh_ip_address, :username
|
83
|
+
|
84
|
+
Fog::SCP.new(ssh_ip_address, username, ssh_options).download(remote_path, local_path, download_options)
|
85
|
+
end
|
86
|
+
|
87
|
+
def ssh(commands, options={}, &blk)
|
88
|
+
require 'net/ssh'
|
89
|
+
requires :ssh_ip_address, :username
|
90
|
+
|
91
|
+
options = ssh_options.merge(options)
|
92
|
+
|
93
|
+
Fog::SSH.new(ssh_ip_address, username, options).run(commands, &blk)
|
94
|
+
end
|
95
|
+
|
96
|
+
def sshable?(options={})
|
97
|
+
ready? && !ssh_ip_address.nil? && !!Timeout::timeout(8) { ssh('pwd', options) }
|
98
|
+
rescue SystemCallError, Net::SSH::AuthenticationFailed, Net::SSH::Disconnect, Timeout::Error
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/fog/core.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# external core dependencies
|
2
|
+
require 'base64'
|
3
|
+
require 'cgi'
|
4
|
+
require 'uri'
|
5
|
+
require 'excon'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'formatador'
|
8
|
+
require 'openssl'
|
9
|
+
require 'time'
|
10
|
+
require 'timeout'
|
11
|
+
require 'ipaddr'
|
12
|
+
|
13
|
+
# internal core dependencies
|
14
|
+
require "fog/version"
|
15
|
+
require 'fog/core/attributes'
|
16
|
+
require 'fog/core/collection'
|
17
|
+
require 'fog/core/connection'
|
18
|
+
require 'fog/core/credentials'
|
19
|
+
require 'fog/core/current_machine'
|
20
|
+
require 'fog/core/deprecation'
|
21
|
+
require 'fog/core/errors'
|
22
|
+
require 'fog/core/hmac'
|
23
|
+
require 'fog/core/logger'
|
24
|
+
require 'fog/core/model'
|
25
|
+
require 'fog/core/mock'
|
26
|
+
require 'fog/core/provider'
|
27
|
+
require 'fog/core/service'
|
28
|
+
require 'fog/core/ssh'
|
29
|
+
require 'fog/core/scp'
|
30
|
+
require 'fog/core/time'
|
31
|
+
require 'fog/core/wait_for'
|
32
|
+
require 'fog/core/wait_for_defaults'
|
33
|
+
require 'fog/core/class_from_string'
|
34
|
+
require 'fog/core/uuid'
|
35
|
+
|
36
|
+
# service wrappers
|
37
|
+
require 'fog/account'
|
38
|
+
require 'fog/billing'
|
39
|
+
require 'fog/cdn'
|
40
|
+
require 'fog/compute'
|
41
|
+
require 'fog/dns'
|
42
|
+
require 'fog/identity'
|
43
|
+
require 'fog/image'
|
44
|
+
require 'fog/metering'
|
45
|
+
require 'fog/monitoring'
|
46
|
+
require 'fog/network'
|
47
|
+
require 'fog/orchestration'
|
48
|
+
require 'fog/storage'
|
49
|
+
require 'fog/support'
|
50
|
+
require 'fog/volume'
|
51
|
+
require 'fog/vpn'
|
@@ -0,0 +1,227 @@
|
|
1
|
+
module Fog
|
2
|
+
module Attributes
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
def _load(marshalled)
|
6
|
+
new(Marshal.load(marshalled))
|
7
|
+
end
|
8
|
+
|
9
|
+
def aliases
|
10
|
+
@aliases ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def attributes
|
14
|
+
@attributes ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def attribute(name, options = {})
|
18
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
19
|
+
def #{name}
|
20
|
+
attributes[:#{name}]
|
21
|
+
end
|
22
|
+
EOS
|
23
|
+
case options[:type]
|
24
|
+
when :boolean
|
25
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
26
|
+
def #{name}=(new_#{name})
|
27
|
+
attributes[:#{name}] = case new_#{name}
|
28
|
+
when true,'true'
|
29
|
+
true
|
30
|
+
when false,'false'
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
EOS
|
35
|
+
when :float
|
36
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
37
|
+
def #{name}=(new_#{name})
|
38
|
+
attributes[:#{name}] = new_#{name}.to_f
|
39
|
+
end
|
40
|
+
EOS
|
41
|
+
when :integer
|
42
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
43
|
+
def #{name}=(new_#{name})
|
44
|
+
attributes[:#{name}] = new_#{name}.to_i
|
45
|
+
end
|
46
|
+
EOS
|
47
|
+
when :string
|
48
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
49
|
+
def #{name}=(new_#{name})
|
50
|
+
attributes[:#{name}] = new_#{name}.to_s
|
51
|
+
end
|
52
|
+
EOS
|
53
|
+
when :time
|
54
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
55
|
+
def #{name}=(new_#{name})
|
56
|
+
attributes[:#{name}] = if new_#{name}.nil? || new_#{name} == "" || new_#{name}.is_a?(Time)
|
57
|
+
new_#{name}
|
58
|
+
else
|
59
|
+
Time.parse(new_#{name})
|
60
|
+
end
|
61
|
+
end
|
62
|
+
EOS
|
63
|
+
when :timestamp
|
64
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
65
|
+
def #{name}=(new_#{name})
|
66
|
+
attributes[:#{name}] = Time.at(new_#{name}.to_i)
|
67
|
+
end
|
68
|
+
EOS
|
69
|
+
when :array
|
70
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
71
|
+
def #{name}=(new_#{name})
|
72
|
+
attributes[:#{name}] = [*new_#{name}]
|
73
|
+
end
|
74
|
+
EOS
|
75
|
+
else
|
76
|
+
if squash = options[:squash]
|
77
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
78
|
+
def #{name}=(new_data)
|
79
|
+
if new_data.is_a?(Hash)
|
80
|
+
if new_data.has_key?(:'#{squash}')
|
81
|
+
attributes[:#{name}] = new_data[:'#{squash}']
|
82
|
+
elsif new_data.has_key?("#{squash}")
|
83
|
+
attributes[:#{name}] = new_data["#{squash}"]
|
84
|
+
else
|
85
|
+
attributes[:#{name}] = [ new_data ]
|
86
|
+
end
|
87
|
+
else
|
88
|
+
attributes[:#{name}] = new_data
|
89
|
+
end
|
90
|
+
end
|
91
|
+
EOS
|
92
|
+
else
|
93
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
94
|
+
def #{name}=(new_#{name})
|
95
|
+
attributes[:#{name}] = new_#{name}
|
96
|
+
end
|
97
|
+
EOS
|
98
|
+
end
|
99
|
+
end
|
100
|
+
@attributes ||= []
|
101
|
+
@attributes |= [name]
|
102
|
+
for new_alias in [*options[:aliases]]
|
103
|
+
aliases[new_alias] = name
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def identity(name, options = {})
|
108
|
+
@identity = name
|
109
|
+
self.attribute(name, options)
|
110
|
+
end
|
111
|
+
|
112
|
+
def ignore_attributes(*args)
|
113
|
+
@ignored_attributes = args.collect {|attr| attr.to_s }
|
114
|
+
end
|
115
|
+
|
116
|
+
def ignored_attributes
|
117
|
+
@ignored_attributes ||= []
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
module InstanceMethods
|
123
|
+
|
124
|
+
def _dump(level)
|
125
|
+
Marshal.dump(attributes)
|
126
|
+
end
|
127
|
+
|
128
|
+
def attributes
|
129
|
+
@attributes ||= {}
|
130
|
+
end
|
131
|
+
|
132
|
+
def dup
|
133
|
+
copy = super
|
134
|
+
copy.dup_attributes!
|
135
|
+
copy
|
136
|
+
end
|
137
|
+
|
138
|
+
def identity
|
139
|
+
send(self.class.instance_variable_get('@identity'))
|
140
|
+
end
|
141
|
+
|
142
|
+
def identity=(new_identity)
|
143
|
+
send("#{self.class.instance_variable_get('@identity')}=", new_identity)
|
144
|
+
end
|
145
|
+
|
146
|
+
def merge_attributes(new_attributes = {})
|
147
|
+
for key, value in new_attributes
|
148
|
+
unless self.class.ignored_attributes.include?(key)
|
149
|
+
if aliased_key = self.class.aliases[key]
|
150
|
+
send("#{aliased_key}=", value)
|
151
|
+
elsif self.respond_to?("#{key}=",true)
|
152
|
+
send("#{key}=", value)
|
153
|
+
else
|
154
|
+
attributes[key] = value
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns true if a remote resource has been assigned an
|
162
|
+
# identity and we can assume it has been persisted.
|
163
|
+
#
|
164
|
+
# @return [Boolean]
|
165
|
+
def persisted?
|
166
|
+
!!identity
|
167
|
+
end
|
168
|
+
|
169
|
+
# Returns true if a remote resource has not been assigned an
|
170
|
+
# identity.
|
171
|
+
#
|
172
|
+
# This was added for a ActiveRecord like feel but has been
|
173
|
+
# outdated by ActiveModel API using {#persisted?}
|
174
|
+
#
|
175
|
+
# @deprecated Use inverted form of {#persisted?}
|
176
|
+
# @return [Boolean]
|
177
|
+
def new_record?
|
178
|
+
Fog::Logger.deprecation("#new_record? is deprecated, use !persisted? instead [light_black](#{caller.first})[/]")
|
179
|
+
!persisted?
|
180
|
+
end
|
181
|
+
|
182
|
+
# check that the attributes specified in args exist and is not nil
|
183
|
+
def requires(*args)
|
184
|
+
missing = missing_attributes(args)
|
185
|
+
if missing.length == 1
|
186
|
+
raise(ArgumentError, "#{missing.first} is required for this operation")
|
187
|
+
elsif missing.any?
|
188
|
+
raise(ArgumentError, "#{missing[0...-1].join(", ")} and #{missing[-1]} are required for this operation")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def requires_one(*args)
|
193
|
+
missing = missing_attributes(args)
|
194
|
+
if missing.length == args.length
|
195
|
+
raise(ArgumentError, "#{missing[0...-1].join(", ")} or #{missing[-1]} are required for this operation")
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
protected
|
200
|
+
|
201
|
+
def missing_attributes(args)
|
202
|
+
missing = []
|
203
|
+
for arg in [:service] | args
|
204
|
+
unless send("#{arg}") || attributes.has_key?(arg)
|
205
|
+
missing << arg
|
206
|
+
end
|
207
|
+
end
|
208
|
+
missing
|
209
|
+
end
|
210
|
+
|
211
|
+
def dup_attributes!
|
212
|
+
@attributes = @attributes.dup if @attributes
|
213
|
+
end
|
214
|
+
|
215
|
+
private
|
216
|
+
|
217
|
+
def remap_attributes(attributes, mapping)
|
218
|
+
for key, value in mapping
|
219
|
+
if attributes.key?(key)
|
220
|
+
attributes[value] = attributes.delete(key)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|