fog-core 2.3.0 → 2.4.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +2 -0
  3. data/.github/workflows/ruby.yml +1 -1
  4. data/.github/workflows/stale.yml +1 -1
  5. data/.rubocop.yml +16 -12
  6. data/.rubocop_todo.yml +724 -0
  7. data/Gemfile +1 -1
  8. data/Rakefile +2 -14
  9. data/changelog.md +14 -0
  10. data/fog-core.gemspec +10 -7
  11. data/lib/fog/compute/models/server.rb +7 -3
  12. data/lib/fog/compute.rb +2 -2
  13. data/lib/fog/core/association.rb +1 -0
  14. data/lib/fog/core/attributes/default.rb +7 -0
  15. data/lib/fog/core/attributes.rb +28 -3
  16. data/lib/fog/core/cache.rb +58 -55
  17. data/lib/fog/core/collection.rb +9 -3
  18. data/lib/fog/core/connection.rb +1 -1
  19. data/lib/fog/core/current_machine.rb +1 -1
  20. data/lib/fog/core/errors.rb +1 -1
  21. data/lib/fog/core/logger.rb +2 -2
  22. data/lib/fog/core/mock.rb +6 -1
  23. data/lib/fog/core/model.rb +34 -5
  24. data/lib/fog/core/provider.rb +7 -7
  25. data/lib/fog/core/scp.rb +15 -11
  26. data/lib/fog/core/service.rb +4 -4
  27. data/lib/fog/core/services_mixin.rb +9 -9
  28. data/lib/fog/core/ssh.rb +3 -2
  29. data/lib/fog/core/stringify_keys.rb +0 -2
  30. data/lib/fog/core/time.rb +2 -2
  31. data/lib/fog/core/uuid.rb +2 -8
  32. data/lib/fog/core/version.rb +1 -1
  33. data/lib/fog/core/wait_for.rb +2 -1
  34. data/lib/fog/core/wait_for_defaults.rb +2 -0
  35. data/lib/fog/core.rb +57 -58
  36. data/lib/fog/formatador.rb +7 -6
  37. data/lib/fog/schema/data_validator.rb +1 -0
  38. data/lib/fog/storage.rb +15 -15
  39. data/lib/fog/test_helpers/collection_helper.rb +2 -0
  40. data/lib/fog/test_helpers/formats_helper.rb +2 -2
  41. data/lib/fog/test_helpers/helper.rb +3 -3
  42. data/lib/fog/test_helpers/minitest/assertions.rb +1 -1
  43. data/lib/fog/test_helpers/minitest/expectations.rb +1 -1
  44. data/lib/fog/test_helpers/mock_helper.rb +84 -84
  45. data/lib/fog/test_helpers/types_helper.rb +1 -0
  46. data/lib/tasks/test_task.rb +2 -2
  47. data/spec/compute/models/server_spec.rb +7 -7
  48. data/spec/compute_spec.rb +6 -6
  49. data/spec/connection_spec.rb +11 -9
  50. data/spec/core/cache_spec.rb +51 -15
  51. data/spec/core/collection_spec.rb +24 -0
  52. data/spec/core/model_spec.rb +36 -3
  53. data/spec/core/stringify_keys_spec.rb +3 -3
  54. data/spec/core/whitelist_keys_spec.rb +2 -2
  55. data/spec/current_machine_spec.rb +2 -2
  56. data/spec/fog_attribute_spec.rb +183 -163
  57. data/spec/formatador_spec.rb +7 -7
  58. data/spec/identity_spec.rb +6 -6
  59. data/spec/mocking_spec.rb +3 -3
  60. data/spec/service_spec.rb +19 -19
  61. data/spec/spec_helper.rb +3 -8
  62. data/spec/storage_spec.rb +6 -6
  63. data/spec/test_helpers/formats_helper_spec.rb +8 -8
  64. data/spec/test_helpers/schema_validator_spec.rb +8 -8
  65. data/spec/utils_spec.rb +6 -6
  66. data/spec/wait_for_spec.rb +2 -2
  67. metadata +44 -53
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
  gemspec
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require 'bundler/gem_tasks'
1
+ require "bundler/gem_tasks"
2
2
 
3
- task :default => [:test]
3
+ task default: [:test]
4
4
 
5
5
  require "rake/testtask"
6
6
 
@@ -9,15 +9,3 @@ Rake::TestTask.new do |t|
9
9
  t.libs << "spec"
10
10
  t.pattern = "spec/**/*_spec.rb"
11
11
  end
12
-
13
- task :travis do
14
- mock = 'true' || ENV['FOG_MOCK']
15
- sh("export FOG_MOCK=#{mock} && rake")
16
-
17
- if ENV['COVERAGE']
18
- require 'coveralls/rake/task'
19
-
20
- Coveralls::RakeTask.new
21
- Rake::Task["coveralls:push"].invoke
22
- end
23
- end
data/changelog.md CHANGED
@@ -1,3 +1,17 @@
1
+ 2.4.0 01/03/2024
2
+ ==========================================================
3
+
4
+ - fixes for caching/restoring collection attributes
5
+ - add explicit CRUD methods to models, make returns more consistent
6
+ - add filter_attributes method
7
+ - allow cache loading with aliases
8
+ - update rubocop config and apply styles/fixes
9
+ - fix minitest compatibility
10
+ - remove coveralls
11
+ - fixes for method delegation for ruby 3.x
12
+ - update ruby versions in test matrix
13
+
14
+
1
15
  2.3.0 03/08/2022
2
16
  ==========================================================
3
17
 
data/fog-core.gemspec CHANGED
@@ -1,5 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require "fog/core/version"
5
6
 
@@ -15,26 +16,28 @@ Gem::Specification.new do |spec|
15
16
 
16
17
  spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = '>= 2.0.0'
21
+ spec.required_ruby_version = ">= 2.0"
22
22
 
23
23
  spec.add_dependency("builder")
24
- spec.add_dependency("mime-types")
25
24
  spec.add_dependency("excon", "~> 0.71")
26
25
  spec.add_dependency("formatador", ">= 0.2", "< 2.0")
26
+ spec.add_dependency("mime-types")
27
27
 
28
28
  # https://github.com/fog/fog-core/issues/206
29
29
  # spec.add_dependency("xmlrpc") if RUBY_VERSION.to_s >= "2.4"
30
30
 
31
- spec.add_development_dependency("tins") if RUBY_VERSION.to_s > "2.0"
32
- spec.add_development_dependency("coveralls")
33
31
  spec.add_development_dependency("minitest")
34
32
  spec.add_development_dependency("minitest-stub-const")
35
33
  spec.add_development_dependency("pry")
36
34
  spec.add_development_dependency("rake")
37
35
  spec.add_development_dependency("rubocop")
36
+ spec.add_development_dependency("rubocop-minitest")
37
+ spec.add_development_dependency("rubocop-rake")
38
38
  spec.add_development_dependency("thor")
39
+ spec.add_development_dependency("tins")
39
40
  spec.add_development_dependency("yard")
41
+
42
+ spec.metadata["rubygems_mfa_required"] = "true"
40
43
  end
@@ -53,12 +53,13 @@ module Fog
53
53
  def ssh_ip_address
54
54
  return public_ip_address unless @ssh_ip_address
55
55
  return @ssh_ip_address.call(self) if @ssh_ip_address.is_a?(Proc)
56
+
56
57
  @ssh_ip_address
57
58
  end
58
59
 
59
60
  def ssh_options
60
61
  @ssh_options ||= {}
61
- ssh_options = @ssh_options.merge(:port => ssh_port)
62
+ ssh_options = @ssh_options.merge(port: ssh_port)
62
63
  if private_key
63
64
  ssh_options[:key_data] = [private_key]
64
65
  ssh_options[:auth_methods] = %w(publickey)
@@ -89,9 +90,12 @@ module Fog
89
90
  end
90
91
 
91
92
  def sshable?(options = {})
92
- result = ready? && !ssh_ip_address.nil? && !!Timeout.timeout(sshable_timeout) { ssh("pwd", options) }
93
+ return false unless ready? && ssh_ip_address
94
+
95
+ Timeout.timeout(sshable_timeout) { ssh("pwd", options) }
93
96
  @sshable_timeout = nil
94
- result
97
+
98
+ true
95
99
  rescue SystemCallError
96
100
  false
97
101
  rescue Net::SSH::AuthenticationFailed, Net::SSH::Disconnect
data/lib/fog/compute.rb CHANGED
@@ -22,10 +22,10 @@ module Fog
22
22
  version = attributes.delete(:version)
23
23
  version = version.to_s.downcase.to_sym unless version.nil?
24
24
  if version == :v1
25
- error_message = 'DigitalOcean V1 is deprecated.Please use `:version => :v2` attribute to use Next Gen Cloud Servers.'
25
+ error_message = "DigitalOcean V1 is deprecated.Please use `:version => :v2` attribute to use Next Gen Cloud Servers."
26
26
  raise error_message
27
27
  else
28
- require 'fog/digitalocean/compute'
28
+ require "fog/digitalocean/compute"
29
29
  Fog::Compute::DigitalOcean.new(attributes)
30
30
  end
31
31
  else
@@ -7,6 +7,7 @@ module Fog
7
7
 
8
8
  def load(associations)
9
9
  return unless associations.kind_of?(Array)
10
+
10
11
  associations.each do |association|
11
12
  self << association
12
13
  end
@@ -7,6 +7,13 @@ module Fog
7
7
  class Default
8
8
  attr_reader :model, :name, :squash, :aliases, :default, :as
9
9
 
10
+ # @param [Klass] model model class
11
+ # @param [Symbol] name name of the attribute
12
+ # @param [Hash] options attribute options
13
+ # @option options [Symbol] :squash
14
+ # @option options [::Array] :aliases
15
+ # @option options [Object] :default
16
+ # @option options [Object] :as
10
17
  def initialize(model, name, options)
11
18
  @model = model
12
19
  @model.attributes << name
@@ -25,6 +25,14 @@ module Fog
25
25
  @masks ||= {}
26
26
  end
27
27
 
28
+ # Defines a new attribute
29
+ # @param [Symbol] name attribute name
30
+ # @param [Hash] options (see {Default#initialize})
31
+ # @option options [Symbol, ::String] :type attribute type (see {Attributes})
32
+ # @option options [Symbol] :squash
33
+ # @option options [::Array] :aliases
34
+ # @option options [Object] :default
35
+ # @option options [Object] :as
28
36
  def attribute(name, options = {})
29
37
  type = options.fetch(:type, "default").to_s.capitalize
30
38
  Fog::Attributes.const_get(type).new(self, name, options)
@@ -125,9 +133,13 @@ module Fog
125
133
  send("#{identity_name}=", new_identity)
126
134
  end
127
135
 
136
+ # Merges attributes into self
137
+ # @note Ignored attributes are not merged (see {ClassMethods.ignored_attributes})
138
+ # @return [self]
128
139
  def merge_attributes(new_attributes = {})
129
140
  new_attributes.each_pair do |key, value|
130
141
  next if self.class.ignored_attributes.include?(key)
142
+
131
143
  if self.class.aliases[key]
132
144
  send("#{self.class.aliases[key]}=", value)
133
145
  elsif self.respond_to?("#{key}=", true)
@@ -139,6 +151,18 @@ module Fog
139
151
  self
140
152
  end
141
153
 
154
+ # Filters attributes by selected attribute names
155
+ # @note In some cases we want to easily get subset of model attributes
156
+ # @note Hash#slice requires Ruby >= 2.5.0
157
+ # @param [Symbol] selected attribute names
158
+ # @return [Hash] new hash with selected attributes
159
+ def filter_attributes(*selected)
160
+ filtered = attributes.select { |a, _| selected.include?(a) }
161
+
162
+ # we should use getters instead of direct accessing attributes hash
163
+ filtered.each_key { |k| filtered[k] = send(k) }
164
+ end
165
+
142
166
  # Returns true if a remote resource has been assigned an
143
167
  # identity and we can assume it has been persisted.
144
168
  #
@@ -166,14 +190,15 @@ module Fog
166
190
  if missing.length == 1
167
191
  raise(ArgumentError, "#{missing.first} is required for this operation")
168
192
  elsif missing.any?
169
- raise(ArgumentError, "#{missing[0...-1].join(", ")} and #{missing[-1]} are required for this operation")
193
+ raise(ArgumentError, "#{missing[0...-1].join(', ')} and #{missing[-1]} are required for this operation")
170
194
  end
171
195
  end
172
196
 
173
197
  def requires_one(*args)
174
198
  missing = missing_attributes(args)
175
199
  return unless missing.length == args.length
176
- raise(ArgumentError, "#{missing[0...-1].join(", ")} or #{missing[-1]} are required for this operation")
200
+
201
+ raise(ArgumentError, "#{missing[0...-1].join(', ')} or #{missing[-1]} are required for this operation")
177
202
  end
178
203
 
179
204
  protected
@@ -181,7 +206,7 @@ module Fog
181
206
  def missing_attributes(args)
182
207
  missing = []
183
208
  ([:service] | args).each do |arg|
184
- missing << arg unless send("#{arg}") || attributes.key?(arg)
209
+ missing << arg unless send(arg.to_s) || attributes.key?(arg)
185
210
  end
186
211
  missing
187
212
  end
@@ -93,6 +93,9 @@ module Fog
93
93
  # see the +namespace_prefix=+ method.
94
94
  SANDBOX = ENV["HOME"] ? File.expand_path("~/.fog-cache") : File.expand_path(".fog-cache")
95
95
 
96
+ # required attributes to load model from cache
97
+ REQUIRED_ATTRIBUTES = [:identity, :collection_klass, :collection_attrs, :model_klass, :model_attrs].freeze
98
+
96
99
  # when a resource is used such as `server.cache.dump` the model klass is passed in
97
100
  # so that it can be identified from a different session.
98
101
  attr_reader :model
@@ -112,26 +115,34 @@ module Fog
112
115
  # collection_klass and model_klass should be the same across all instances
113
116
  # choose a valid cache record from the dump to use as a sample to deterine
114
117
  # which collection/model to instantiate.
115
- sample_path = cache_files.detect{ |path| valid_for_load?(path) }
116
- model_klass = const_get_compat(load_cache(sample_path)[:model_klass])
117
- collection_klass = const_get_compat(load_cache(sample_path)[:collection_klass]) if load_cache(sample_path)[:collection_klass]
118
+ sample_path = cache_files.detect { |path| valid_for_load?(path) }
119
+ model_klass = Object.const_get(load_cache(sample_path)[:model_klass])
120
+ collection_klass = Object.const_get(load_cache(sample_path)[:collection_klass]) if load_cache(sample_path)[:collection_klass]
118
121
 
119
122
  # Load the cache data into actual ruby instances
120
123
  loaded = cache_files.map do |path|
121
- model_klass.new(load_cache(path)[:attrs]) if valid_for_load?(path)
122
- end.compact
124
+ next unless valid_for_load?(path)
123
125
 
124
- # Set the collection and service so they can be reloaded/connection is set properly.
125
- # See https://github.com/fog/fog-aws/issues/354#issuecomment-286789702
126
- loaded.each do |i|
127
- i.collection = collection_klass.new(:service => service) if collection_klass
128
- i.instance_variable_set(:@service, service)
129
- end
126
+ cache = load_cache(path)
127
+
128
+ # make sure attributes are not nil
129
+ cache[:collection_attrs] ||= {}
130
+ cache[:model_attrs] ||= {}
131
+
132
+ m = model_klass.new(cache[:model_attrs])
133
+
134
+ # Set the collection and service so they can be reloaded/connection is set properly.
135
+ # See https://github.com/fog/fog-aws/issues/354#issuecomment-286789702
136
+ m.instance_variable_set(:@service, service)
137
+ m.collection = collection_klass.new(cache[:collection_attrs].merge(service: service)) if collection_klass
138
+
139
+ m
140
+ end.compact
130
141
 
131
142
  # uniqe-ify based on the total of attributes. duplicate cache can exist due to
132
143
  # `model#identity` not being unique. but if all attributes match, they are unique
133
144
  # and shouldn't be loaded again.
134
- uniq_loaded = uniq_w_block(loaded) { |i| i.attributes }
145
+ uniq_loaded = loaded.uniq { |i| i.attributes }
135
146
  if uniq_loaded.size != loaded.size
136
147
  Fog::Logger.warning("Found duplicate items in the cache. Expire all & refresh cache soon.")
137
148
  end
@@ -142,38 +153,18 @@ module Fog
142
153
  uniq_loaded
143
154
  end
144
155
 
145
- # :nodoc: compatability for 1.8.7 1.9.3
146
- def self.const_get_compat(strklass)
147
- # https://stackoverflow.com/questions/3163641/get-a-class-by-name-in-ruby
148
- strklass.split('::').inject(Object) do |mod, class_name|
149
- mod.const_get(class_name)
150
- end
151
- end
152
-
153
- # :nodoc: compatability for 1.8.7 1.9.3
154
- def self.uniq_w_block(arr)
155
- ret, keys = [], []
156
- arr.each do |x|
157
- key = block_given? ? yield(x) : x
158
- unless keys.include? key
159
- ret << x
160
- keys << key
161
- end
162
- end
163
- ret
164
- end
165
-
166
156
  # method to determine if a path can be loaded and is valid fog cache format.
167
157
  def self.valid_for_load?(path)
168
158
  data = load_cache(path)
169
159
  if data && data.is_a?(Hash)
170
- if [:identity, :model_klass, :collection_klass, :attrs].all? { |k| data.keys.include?(k) }
171
- return true
172
- else
173
- Fog::Logger.warning("Found corrupt items in the cache: #{path}. Expire all & refresh cache soon.\n\nData:#{File.read(path)}")
174
- return false
175
- end
160
+ missing_attrs = REQUIRED_ATTRIBUTES.reject { |k| data.keys.include?(k) }
161
+ return true if missing_attrs.empty?
162
+
163
+ Fog::Logger.warning("Found corrupt items in the cache: #{path}. Expire all & refresh cache soon.\n\nMissing: #{missing_attrs}.\nData:\n#{File.read(path)}")
164
+ return false
176
165
  end
166
+
167
+ false
177
168
  end
178
169
 
179
170
  # creates on-disk cache of this specific +model_klass+ and +@service+
@@ -193,12 +184,23 @@ module Fog
193
184
  FileUtils.rm_rf(SANDBOX)
194
185
  end
195
186
 
187
+ # Load YAML file with aliases
188
+ # @note Starting from Ruby 3.1 we must explicitly tell Psych to allow aliases
189
+ def self.yaml_load(path)
190
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.1.0")
191
+ YAML.load(path, aliases: true)
192
+ else
193
+ YAML.load(path)
194
+ end
195
+ end
196
+
196
197
  # loads yml cache from path on disk, used
197
198
  # to initialize Fog models.
198
199
  def self.load_cache(path)
199
200
  @memoized ||= {}
200
201
  return @memoized[path] if @memoized[path]
201
- @memoized[path] = YAML.load(File.read(path))
202
+
203
+ @memoized[path] = yaml_load(File.read(path))
202
204
  end
203
205
 
204
206
  def self.namespace_prefix=(name)
@@ -222,13 +224,13 @@ module Fog
222
224
 
223
225
  mpath = File.join(SANDBOX, namespace_prefix, "metadata.yml")
224
226
  to_write = if File.exist?(mpath)
225
- YAML.dump(YAML.load(File.read(mpath)).merge!(h))
226
- else
227
- YAML.dump(h)
228
- end
227
+ YAML.dump(yaml_load(File.read(mpath)).merge!(h))
228
+ else
229
+ YAML.dump(h)
230
+ end
229
231
 
230
232
  mdir = File.join(SANDBOX, namespace_prefix)
231
- FileUtils.mkdir_p(mdir) if !File.exist?(mdir)
233
+ FileUtils.mkdir_p(mdir)
232
234
 
233
235
  File.open(mpath, "w") { |f| f.write(to_write) }
234
236
  end
@@ -237,10 +239,9 @@ module Fog
237
239
  def self.metadata
238
240
  mpath = File.join(SANDBOX, namespace_prefix, "metadata.yml")
239
241
  if File.exist?(mpath)
240
- metadata = YAML.load(File.read(mpath))
241
- return metadata
242
+ yaml_load(File.read(mpath))
242
243
  else
243
- return {}
244
+ {}
244
245
  end
245
246
  end
246
247
 
@@ -249,11 +250,10 @@ module Fog
249
250
 
250
251
  raise CacheDir.new("Must set an explicit identifier/name for this cache. Example: 'serviceX-regionY'") unless namespace_prefix
251
252
 
252
- ns = File.join(SANDBOX, namespace_prefix, service.class.to_s, model_klass.to_s)
253
- ns = safe_path(ns)
253
+ File.join(SANDBOX, namespace_prefix, safe_class_path(service.class), safe_class_path(model_klass))
254
254
  end
255
255
 
256
- def self.safe_path(klass)
256
+ def self.safe_class_path(klass)
257
257
  klass.to_s.gsub("::", "_").downcase
258
258
  end
259
259
 
@@ -269,10 +269,13 @@ module Fog
269
269
  self.class.create_namespace(model.class, model.service)
270
270
  end
271
271
 
272
- data = { :identity => model.identity,
273
- :model_klass => model.class.to_s,
274
- :collection_klass => model.collection && model.collection.class.to_s,
275
- :attrs => model.attributes }
272
+ data = {
273
+ identity: model.identity,
274
+ model_klass: model.class.to_s,
275
+ collection_klass: model.collection && model.collection.class.to_s,
276
+ collection_attrs: model.collection && model.collection.attributes,
277
+ model_attrs: model.attributes
278
+ }
276
279
 
277
280
  File.open(dump_to, "w") { |f| f.write(YAML.dump(data)) }
278
281
  end
@@ -11,6 +11,7 @@ module Fog
11
11
 
12
12
  Array.public_instance_methods(false).each do |method|
13
13
  next if [:reject, :select, :slice, :clear, :inspect].include?(method.to_sym)
14
+
14
15
  class_eval <<-EOS, __FILE__, __LINE__
15
16
  def #{method}(*args)
16
17
  unless @loaded
@@ -18,6 +19,7 @@ module Fog
18
19
  end
19
20
  super
20
21
  end
22
+ ruby2_keywords(method) if respond_to?(:ruby2_keywords, true)
21
23
  EOS
22
24
  end
23
25
 
@@ -30,6 +32,7 @@ module Fog
30
32
  data = super
31
33
  self.clone.clear.concat(data)
32
34
  end
35
+ ruby2_keywords(method) if respond_to?(:ruby2_keywords, true)
33
36
  EOS
34
37
  end
35
38
 
@@ -52,7 +55,7 @@ module Fog
52
55
  end
53
56
 
54
57
  def destroy(identity)
55
- new(:identity => identity).destroy
58
+ new(identity: identity).destroy
56
59
  end
57
60
 
58
61
  # Creates a new Fog::Collection based around the passed service
@@ -85,10 +88,11 @@ module Fog
85
88
  unless attributes.is_a?(::Hash)
86
89
  raise ArgumentError, "Initialization parameters must be an attributes hash, got #{attributes.class} #{attributes.inspect}"
87
90
  end
91
+
88
92
  model.new(
89
93
  {
90
- :collection => self,
91
- :service => service
94
+ collection: self,
95
+ service: service
92
96
  }.merge(attributes)
93
97
  )
94
98
  end
@@ -112,6 +116,7 @@ module Fog
112
116
  all
113
117
  end
114
118
  end
119
+
115
120
  # Base class for collection classes whose 'all' method returns only a single
116
121
  # page of results and passes the 'Marker' option along as
117
122
  # self.filters[:marker]
@@ -120,6 +125,7 @@ module Fog
120
125
  if block_given?
121
126
  Kernel.loop do
122
127
  break unless filters[:marker]
128
+
123
129
  page = all(collection_filters)
124
130
  # We need to explicitly use the base 'each' method here on the page,
125
131
  # otherwise we get infinite recursion
@@ -52,7 +52,7 @@ module Fog
52
52
 
53
53
  params[:debug_response] = true unless params.key?(:debug_response)
54
54
  params[:headers] ||= {}
55
- params.merge!(:persistent => params.fetch(:persistent, persistent))
55
+ params.merge!(persistent: params.fetch(:persistent, persistent))
56
56
  params[:headers]["User-Agent"] ||= user_agent
57
57
  @excon = Excon.new(url, params)
58
58
  end
@@ -4,7 +4,7 @@ module Fog
4
4
  class CurrentMachine
5
5
  @lock = Mutex.new
6
6
 
7
- AMAZON_AWS_CHECK_IP = "http://checkip.amazonaws.com"
7
+ AMAZON_AWS_CHECK_IP = "http://checkip.amazonaws.com".freeze
8
8
 
9
9
  def self.ip_address=(ip_address)
10
10
  @lock.synchronize do
@@ -120,7 +120,7 @@ An alternate file may be used by placing its path in the FOG_RC environment vari
120
120
  # End of Fog Credentials File
121
121
  #######################################################
122
122
 
123
- YML
123
+ YML
124
124
  raise Fog::Errors::LoadError, missing_credentials_message
125
125
  end
126
126
  end
@@ -1,8 +1,8 @@
1
1
  module Fog
2
2
  class Logger
3
3
  @channels = {
4
- :deprecation => ::STDERR,
5
- :warning => ::STDERR
4
+ deprecation: ::STDERR,
5
+ warning: ::STDERR
6
6
  }
7
7
 
8
8
  @channels[:debug] = ::STDERR if ENV["DEBUG"]
data/lib/fog/core/mock.rb CHANGED
@@ -25,6 +25,7 @@ module Fog
25
25
 
26
26
  def self.delay=(new_delay)
27
27
  raise ArgumentError, "delay must be non-negative" unless new_delay >= 0
28
+
28
29
  @delay = new_delay
29
30
  end
30
31
 
@@ -32,7 +33,7 @@ module Fog
32
33
  raise Fog::Errors::MockNotImplemented, message
33
34
  end
34
35
 
35
- def self.random_ip(opts = { :version => :v4 })
36
+ def self.random_ip(opts = { version: :v4 })
36
37
  version = opts[:version]
37
38
  if version == :v6
38
39
  bit_length = 128
@@ -92,12 +93,15 @@ module Fog
92
93
  mocked_services = []
93
94
  Fog.constants.map do |x|
94
95
  next if Fog.autoload?(x)
96
+
95
97
  x_const = Fog.const_get(x)
96
98
  x_const.respond_to?(:constants) && x_const.constants.map do |y|
97
99
  next if x_const.autoload?(y)
100
+
98
101
  y_const = x_const.const_get(y)
99
102
  y_const.respond_to?(:constants) && y_const.constants.map do |z|
100
103
  next if y_const.autoload?(z)
104
+
101
105
  mocked_services << y_const.const_get(z) if z.to_sym == :Mock
102
106
  end
103
107
  end
@@ -105,6 +109,7 @@ module Fog
105
109
 
106
110
  mocked_services.each do |mocked_service|
107
111
  next unless mocked_service.respond_to?(:reset)
112
+
108
113
  mocked_service.reset
109
114
  end
110
115
  end
@@ -21,6 +21,33 @@ module Fog
21
21
  merge_attributes(attribs)
22
22
  end
23
23
 
24
+ # Creates new or updates existing model
25
+ # @return [self]
26
+ def save
27
+ persisted? ? update : create
28
+ end
29
+
30
+ # Creates new entity from model
31
+ # @raise [Fog::Errors::NotImplemented] you must implement #create method in child class and return self
32
+ # @return [self]
33
+ def create
34
+ raise Fog::Errors::NotImplemented, "Implement method #create for #{self.class}. Method must return self"
35
+ end
36
+
37
+ # Updates new entity with model
38
+ # @raise [Fog::Errors::NotImplemented] you must implement #update method in child class and return self
39
+ # @return [self]
40
+ def update
41
+ raise Fog::Errors::NotImplemented, "Implement method #update for #{self.class}. Method must return self"
42
+ end
43
+
44
+ # Destroys entity by model identity
45
+ # @raise [Fog::Errors::NotImplemented] you must implement #destroy method in child class and return self
46
+ # @return [self]
47
+ def destroy
48
+ raise Fog::Errors::NotImplemented, "Implement method #destroy for #{self.class}. Method must return self"
49
+ end
50
+
24
51
  def cache
25
52
  Fog::Cache.new(self)
26
53
  end
@@ -41,6 +68,8 @@ module Fog
41
68
  end
42
69
  end
43
70
 
71
+ # @return [self] if model successfully reloaded
72
+ # @return [nil] if something went wrong or model was not found
44
73
  def reload
45
74
  requires :identity
46
75
 
@@ -61,6 +90,7 @@ module Fog
61
90
 
62
91
  def symbolize_keys(hash)
63
92
  return nil if hash.nil?
93
+
64
94
  hash.reduce({}) do |options, (key, value)|
65
95
  options[(key.to_sym rescue key) || key] = value
66
96
  options
@@ -69,6 +99,7 @@ module Fog
69
99
 
70
100
  def wait_for(timeout = Fog.timeout, interval = Fog.interval, &block)
71
101
  reload_has_succeeded = false
102
+
72
103
  duration = Fog.wait_for(timeout, interval) do # Note that duration = false if it times out
73
104
  if reload
74
105
  reload_has_succeeded = true
@@ -77,11 +108,9 @@ module Fog
77
108
  false
78
109
  end
79
110
  end
80
- if reload_has_succeeded
81
- return duration # false if timeout; otherwise {:duration => elapsed time }
82
- else
83
- raise Fog::Errors::Error, "Reload failed, #{self.class} #{identity} not present."
84
- end
111
+ raise Fog::Errors::Error, "Reload failed, #{self.class} #{identity} not present." unless reload_has_succeeded
112
+
113
+ duration # false if timeout; otherwise {:duration => elapsed time }
85
114
  end
86
115
  end
87
116
  end
@@ -18,11 +18,11 @@ module Fog
18
18
  private
19
19
 
20
20
  def underscore_name(string)
21
- string.gsub(/::/, '/').
22
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
23
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
24
- tr("-", "_").
25
- downcase
21
+ string.gsub(/::/, "/")
22
+ .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
23
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
24
+ .tr("-", "_")
25
+ .downcase
26
26
  end
27
27
  end
28
28
 
@@ -49,7 +49,7 @@ module Fog
49
49
  [to_s, constant_string].join("::")
50
50
  else
51
51
  provider = to_s.split("::").last
52
- Fog::Logger.deprecation("Unable to load #{[to_s, constant_string].join("::")}")
52
+ Fog::Logger.deprecation("Unable to load #{[to_s, constant_string].join('::')}")
53
53
  Fog::Logger.deprecation(
54
54
  format(
55
55
  Fog::ServicesMixin::E_SERVICE_PROVIDER_CONSTANT,
@@ -57,7 +57,7 @@ module Fog
57
57
  provider: provider
58
58
  )
59
59
  )
60
- ['Fog', constant_string, provider].join("::")
60
+ ["Fog", constant_string, provider].join("::")
61
61
  end
62
62
  end
63
63
  end