fog-core 2.3.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +2 -0
- data/.github/dependabot.yml +2 -2
- data/.github/workflows/ci.yml +32 -0
- data/.rubocop.yml +16 -12
- data/.rubocop_todo.yml +724 -0
- data/Gemfile +1 -1
- data/README.md +2 -1
- data/Rakefile +2 -14
- data/SECURITY.md +6 -0
- data/changelog.md +26 -0
- data/fog-core.gemspec +11 -8
- data/lib/fog/compute/models/server.rb +7 -3
- data/lib/fog/compute.rb +3 -3
- data/lib/fog/core/association.rb +1 -0
- data/lib/fog/core/attributes/default.rb +7 -0
- data/lib/fog/core/attributes.rb +28 -3
- data/lib/fog/core/cache.rb +58 -55
- data/lib/fog/core/collection.rb +9 -3
- data/lib/fog/core/connection.rb +1 -1
- data/lib/fog/core/current_machine.rb +1 -1
- data/lib/fog/core/errors.rb +1 -1
- data/lib/fog/core/logger.rb +2 -2
- data/lib/fog/core/mock.rb +7 -2
- data/lib/fog/core/model.rb +34 -5
- data/lib/fog/core/provider.rb +7 -7
- data/lib/fog/core/scp.rb +15 -11
- data/lib/fog/core/service.rb +5 -5
- data/lib/fog/core/services_mixin.rb +9 -9
- data/lib/fog/core/ssh.rb +3 -2
- data/lib/fog/core/stringify_keys.rb +0 -2
- data/lib/fog/core/time.rb +2 -2
- data/lib/fog/core/uuid.rb +2 -8
- data/lib/fog/core/version.rb +1 -1
- data/lib/fog/core/wait_for.rb +2 -1
- data/lib/fog/core/wait_for_defaults.rb +2 -0
- data/lib/fog/core.rb +57 -59
- data/lib/fog/formatador.rb +9 -8
- data/lib/fog/schema/data_validator.rb +1 -0
- data/lib/fog/storage.rb +15 -16
- data/lib/fog/test_helpers/collection_helper.rb +2 -0
- data/lib/fog/test_helpers/formats_helper.rb +2 -2
- data/lib/fog/test_helpers/helper.rb +3 -3
- data/lib/fog/test_helpers/minitest/assertions.rb +1 -1
- data/lib/fog/test_helpers/minitest/expectations.rb +1 -1
- data/lib/fog/test_helpers/mock_helper.rb +84 -84
- data/lib/fog/test_helpers/types_helper.rb +1 -0
- data/lib/tasks/test_task.rb +4 -5
- metadata +46 -81
- data/.github/workflows/ruby.yml +0 -18
- data/.github/workflows/stale.yml +0 -9
- data/spec/compute/models/server_spec.rb +0 -229
- data/spec/compute_spec.rb +0 -95
- data/spec/connection_spec.rb +0 -105
- data/spec/core/cache_spec.rb +0 -191
- data/spec/core/model_spec.rb +0 -36
- data/spec/core/stringify_keys_spec.rb +0 -38
- data/spec/core/whitelist_keys_spec.rb +0 -36
- data/spec/credentials_spec.rb +0 -88
- data/spec/current_machine_spec.rb +0 -36
- data/spec/fake_app/fake_service.rb +0 -18
- data/spec/fake_app/models/collection.rb +0 -5
- data/spec/fake_app/models/model.rb +0 -2
- data/spec/fake_app/requests/request.rb +0 -11
- data/spec/fog_attribute_spec.rb +0 -549
- data/spec/formatador_spec.rb +0 -154
- data/spec/identity_spec.rb +0 -95
- data/spec/mocking_spec.rb +0 -84
- data/spec/service_spec.rb +0 -201
- data/spec/spec_helper.rb +0 -19
- data/spec/storage_spec.rb +0 -112
- data/spec/test_helpers/formats_helper_spec.rb +0 -121
- data/spec/test_helpers/schema_validator_spec.rb +0 -101
- data/spec/timeout_spec.rb +0 -20
- data/spec/utils_spec.rb +0 -29
- data/spec/uuid_spec.rb +0 -11
- data/spec/wait_for_spec.rb +0 -30
data/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
gemspec
|
data/README.md
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
Shared classes and tests for fog providers and services.
|
4
4
|
|
5
|
-
[![Build Status](https://github.com/fog/fog-core/actions/workflows/
|
5
|
+
[![Build Status](https://github.com/fog/fog-core/actions/workflows/ci.yml/badge.svg)](https://github.com/fog/fog-core/actions/workflows/ci.yml)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/fog-core.svg)](https://rubygems.org/gems/fog-core)
|
6
7
|
|
7
8
|
## Ruby version
|
8
9
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "bundler/gem_tasks"
|
2
2
|
|
3
|
-
task :
|
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/SECURITY.md
ADDED
data/changelog.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
2.5.0 08/02/2024
|
2
|
+
==========================================================
|
3
|
+
|
4
|
+
- drop spec files from gem package
|
5
|
+
- fix 3.4+ ruby issues (string literals and base64)
|
6
|
+
- bump rubocop target
|
7
|
+
- remove stale actions
|
8
|
+
- fixes to ci
|
9
|
+
- add security policy
|
10
|
+
- add gem version badge
|
11
|
+
- add funding info
|
12
|
+
|
13
|
+
2.4.0 01/03/2024
|
14
|
+
==========================================================
|
15
|
+
|
16
|
+
- fixes for caching/restoring collection attributes
|
17
|
+
- add explicit CRUD methods to models, make returns more consistent
|
18
|
+
- add filter_attributes method
|
19
|
+
- allow cache loading with aliases
|
20
|
+
- update rubocop config and apply styles/fixes
|
21
|
+
- fix minitest compatibility
|
22
|
+
- remove coveralls
|
23
|
+
- fixes for method delegation for ruby 3.x
|
24
|
+
- update ruby versions in test matrix
|
25
|
+
|
26
|
+
|
1
27
|
2.3.0 03/08/2022
|
2
28
|
==========================================================
|
3
29
|
|
data/fog-core.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
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
|
|
@@ -13,28 +14,30 @@ Gem::Specification.new do |spec|
|
|
13
14
|
spec.homepage = "https://github.com/fog/fog-core"
|
14
15
|
spec.license = "MIT"
|
15
16
|
|
16
|
-
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR).reject {|f| f.start_with? ('spec/') }
|
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 =
|
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(:
|
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
|
-
|
93
|
+
return false unless ready? && ssh_ip_address
|
94
|
+
|
95
|
+
Timeout.timeout(sshable_timeout) { ssh("pwd", options) }
|
93
96
|
@sshable_timeout = nil
|
94
|
-
|
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,14 +22,14 @@ 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 =
|
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
|
28
|
+
require "fog/digitalocean/compute"
|
29
29
|
Fog::Compute::DigitalOcean.new(attributes)
|
30
30
|
end
|
31
31
|
else
|
32
|
-
super
|
32
|
+
super
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
data/lib/fog/core/association.rb
CHANGED
@@ -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
|
data/lib/fog/core/attributes.rb
CHANGED
@@ -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(
|
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
|
-
|
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(
|
209
|
+
missing << arg unless send(arg.to_s) || attributes.key?(arg)
|
185
210
|
end
|
186
211
|
missing
|
187
212
|
end
|
data/lib/fog/core/cache.rb
CHANGED
@@ -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 =
|
117
|
-
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
|
-
|
122
|
-
end.compact
|
124
|
+
next unless valid_for_load?(path)
|
123
125
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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 =
|
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
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
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
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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)
|
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
|
-
|
241
|
-
return metadata
|
242
|
+
yaml_load(File.read(mpath))
|
242
243
|
else
|
243
|
-
|
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
|
-
|
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.
|
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 = {
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
data/lib/fog/core/collection.rb
CHANGED
@@ -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(:
|
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
|
-
:
|
91
|
-
:
|
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
|
data/lib/fog/core/connection.rb
CHANGED
@@ -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!(:
|
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
|
data/lib/fog/core/errors.rb
CHANGED
@@ -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
|
-
|
123
|
+
YML
|
124
124
|
raise Fog::Errors::LoadError, missing_credentials_message
|
125
125
|
end
|
126
126
|
end
|
data/lib/fog/core/logger.rb
CHANGED
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 = { :
|
36
|
+
def self.random_ip(opts = { version: :v4 })
|
36
37
|
version = opts[:version]
|
37
38
|
if version == :v6
|
38
39
|
bit_length = 128
|
@@ -80,7 +81,7 @@ module Fog
|
|
80
81
|
end
|
81
82
|
|
82
83
|
def self.random_selection(characters, length)
|
83
|
-
selection = ""
|
84
|
+
selection = +""
|
84
85
|
length.times do
|
85
86
|
position = rand(characters.length)
|
86
87
|
selection << characters[position..position]
|
@@ -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
|