fog-core 1.22.0 → 1.23.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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTNmYzY5ZmZiYjA4OTVkZWU2MTA0OTQ3ZmVmZmYxM2M0Y2UxY2ZkMA==
4
+ ODU0ZTJhZDcwMGI0NzRiNmY1ODdjM2NmMDc2ZDMzYWM5NTk1ZjcwYw==
5
5
  data.tar.gz: !binary |-
6
- MGJmMDEwODNmZjRiYjA5MTYzMmNkZjA3OTY4NTAzNzAzZGJkZjE0ZQ==
6
+ MzExN2UxODJlZDg5ZGQzZDIxNjM3YzUzMzc1MDI1MmZmMmJlNzg4Yg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTNmYzVjYzdjMmJiN2NjMjU3ZmFmYTYxZGJiYTA1MTEzZjBmNWFmMWY3Zjg0
10
- NDU0YTcxYWY5ZTU0ODViMGIwMTYyN2IzMWI4YWFlOTVhZjgyYjM5ODU0MTcx
11
- ZTY2MGZkZTVmYmFlMDI4NmVlZGFkNWMxMmY1YTcyOWZhNjJlYTc=
9
+ MTIyZTRhZDg0ZWVjYWY3OTQyNTZhZmY4Y2YzYTBjMDYxYTZhZTQ5N2RiMGRh
10
+ OTMxODUyOGIxYTIwZmYyZGM3NWU4MTc0NTU0OTU4NjI2MzJkODVjYmYzOThl
11
+ OTI2N2MxZjdmOTJiN2IzOTVjZDUwODE5NmEyY2FiOGJmNWEwMGU=
12
12
  data.tar.gz: !binary |-
13
- YTgyMTQ0MWQzOWI5NWM5OWYwNjcxZTE3NWExNWNhZmM1ODU0Y2RlNTNmMDlm
14
- NGFjOThlNDNkNDNmMjA4YTlkNTU4NmU0YjRjNmE4Mzk0ZTExODYyODQzMzg4
15
- OWVlZmQxNDRlM2U2YzViY2ZhOTA0MGY2YzUwOTFjNjFiZWQ2OWI=
13
+ NmQ3NDdjZTM4OGY1ZTI1MTc0M2FiNWQ5YmRmM2FlYjlhNDE3MWNhYjEwMmY3
14
+ NDE0MDNhZDQ5ZTQyYmJhMTliMTI2NzhmZDUyYmVkZThlMDFhMDg0MDA1NTBi
15
+ OWRkMzNlMDUxNTYyYjM4ZDczNTljZWZmZmY5NDE5YTgwNDEzOTM=
@@ -2,6 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem 'nokogiri', '~>1.5.11'
4
4
  gem 'mime-types', '~>1.16'
5
+ gem 'rest-client', '~> 1.6.7'
5
6
 
6
7
  group :development, :test do
7
8
  gem 'rake', '~> 10.1.0'
data/Rakefile CHANGED
@@ -24,7 +24,7 @@ end
24
24
  #require "tasks/changelog_task"
25
25
  #Fog::Rake::ChangelogTask.new
26
26
  task :coveralls_push_workaround do
27
- use_coveralls = (Gem::Version.new(RUBY_VERSION) > Gem::Version.new('1.9.2'))
27
+ use_coveralls = (Gem::Version.new(RUBY_VERSION.dup) > Gem::Version.new('1.9.2'))
28
28
  if (ENV['COVERAGE'] != 'false') && use_coveralls
29
29
  require 'coveralls/rake/task'
30
30
  Coveralls::RakeTask.new
@@ -1,3 +1,40 @@
1
+ 1.23.0 07/16/2014
2
+ ==========================================================
3
+
4
+ attribute whitelisting
5
+ abstract out stringify for possible reuse
6
+ more specific naming
7
+ reorg
8
+ add path_prefix
9
+ fix time conversion to work with XMLRPC
10
+ add more specific per-type attribute tests
11
+ lock down rest-client for 1.8.7
12
+ allow namespace flipflop for dns
13
+ fix identity lookup
14
+ better default attribute value setting
15
+ bump excon
16
+
17
+ 1.22.0 04/17/2014 1c086852e40e4c1ad7ed138834e4a1505ddb1416
18
+ ==========================================================
19
+
20
+ attribute whitelisting
21
+ abstract out stringify for possible reuse
22
+ more specific naming
23
+ reorg
24
+ add path_prefix
25
+ fix time conversion to work with XMLRPC
26
+ add more specific per-type attribute tests
27
+ lock down rest-client for 1.8.7
28
+ allow namespace flipflop for dns
29
+ fix identity lookup
30
+ better default attribute value setting
31
+ bump excon
32
+
33
+ 1.22.0 04/17/2014 1c086852e40e4c1ad7ed138834e4a1505ddb1416
34
+ ==========================================================
35
+
36
+ tests/cleanup/fixes
37
+
1
38
  1.21.1 03/18/2014 3a803405ba60ded421f4bd14677cd3c76cb7e6ab
2
39
  ==========================================================
3
40
 
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency('builder')
22
- spec.add_dependency('excon', '~>0.33')
22
+ spec.add_dependency('excon', '~>0.38')
23
23
  spec.add_dependency('formatador', '~>0.2')
24
24
  spec.add_dependency('mime-types')
25
25
  spec.add_dependency('net-scp', '~>1.1')
@@ -13,6 +13,14 @@ require 'ipaddr'
13
13
  # internal core dependencies
14
14
  require "fog/version"
15
15
  require 'fog/core/attributes'
16
+ require 'fog/core/attributes/default'
17
+ require 'fog/core/attributes/boolean'
18
+ require 'fog/core/attributes/float'
19
+ require 'fog/core/attributes/integer'
20
+ require 'fog/core/attributes/string'
21
+ require 'fog/core/attributes/time'
22
+ require 'fog/core/attributes/timestamp'
23
+ require 'fog/core/attributes/array'
16
24
  require 'fog/core/collection'
17
25
  require 'fog/core/connection'
18
26
  require 'fog/core/credentials'
@@ -32,6 +40,8 @@ require 'fog/core/utils'
32
40
  require 'fog/core/wait_for'
33
41
  require 'fog/core/wait_for_defaults'
34
42
  require 'fog/core/uuid'
43
+ require 'fog/core/stringify_keys'
44
+ require 'fog/core/whitelist_keys'
35
45
 
36
46
  # service wrappers
37
47
  require 'fog/account'
@@ -14,92 +14,17 @@ module Fog
14
14
  @attributes ||= []
15
15
  end
16
16
 
17
+ def default_values
18
+ @default_values ||= {}
19
+ end
20
+
17
21
  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]]
22
+ type = options.fetch(:type, 'default').to_s.capitalize
23
+ default = options.fetch(:default, false)
24
+ Fog::Attributes::const_get(type).new(self, name, options).create
25
+ attributes << name
26
+ default_values[name] = default if default
27
+ Array(options[:aliases]).each do |new_alias|
103
28
  aliases[new_alias] = name
104
29
  end
105
30
  end
@@ -0,0 +1,13 @@
1
+ module Fog
2
+ module Attributes
3
+ class Array < Default
4
+ def create_setter
5
+ model.class_eval <<-EOS, __FILE__, __LINE__
6
+ def #{name}=(new_#{name})
7
+ attributes[:#{name}] = [*new_#{name}]
8
+ end
9
+ EOS
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module Fog
2
+ module Attributes
3
+ class Boolean < Default
4
+ def create_setter
5
+ model.class_eval <<-EOS, __FILE__, __LINE__
6
+ def #{name}=(new_#{name})
7
+ attributes[:#{name}] = case new_#{name}
8
+ when true,'true'
9
+ true
10
+ when false,'false'
11
+ false
12
+ end
13
+ end
14
+ EOS
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,55 @@
1
+ module Fog
2
+ module Attributes
3
+ class Default
4
+ attr_reader :model, :name, :squash
5
+
6
+ def initialize(model, name, options)
7
+ @model = model
8
+ @name = name
9
+ @squash = options.fetch(:squash, false)
10
+ end
11
+
12
+ def create
13
+ create_setter
14
+ create_getter
15
+ end
16
+
17
+ def create_setter
18
+ if squash
19
+ model.class_eval <<-EOS, __FILE__, __LINE__
20
+ def #{name}=(new_data)
21
+ if new_data.is_a?(Hash)
22
+ if new_data.has_key?(:'#{squash}')
23
+ attributes[:#{name}] = new_data[:'#{squash}']
24
+ elsif new_data.has_key?("#{squash}")
25
+ attributes[:#{name}] = new_data["#{squash}"]
26
+ else
27
+ attributes[:#{name}] = [ new_data ]
28
+ end
29
+ else
30
+ attributes[:#{name}] = new_data
31
+ end
32
+ end
33
+ EOS
34
+ else
35
+ model.class_eval <<-EOS, __FILE__, __LINE__
36
+ def #{name}=(new_#{name})
37
+ attributes[:#{name}] = new_#{name}
38
+ end
39
+ EOS
40
+ end
41
+ end
42
+
43
+ def create_getter
44
+ model.class_eval <<-EOS, __FILE__, __LINE__
45
+ def #{name}
46
+ if self.class.default_values[:#{name}] && !persisted?
47
+ return self.class.default_values[:#{name}]
48
+ end
49
+ attributes[:#{name}]
50
+ end
51
+ EOS
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ module Fog
2
+ module Attributes
3
+ class Float < Default
4
+ def create_setter
5
+ model.class_eval <<-EOS, __FILE__, __LINE__
6
+ def #{name}=(new_#{name})
7
+ attributes[:#{name}] = new_#{name}.to_f
8
+ end
9
+ EOS
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Fog
2
+ module Attributes
3
+ class Integer < Default
4
+ def create_setter
5
+ model.class_eval <<-EOS, __FILE__, __LINE__
6
+ def #{name}=(new_#{name})
7
+ attributes[:#{name}] = new_#{name}.to_i
8
+ end
9
+ EOS
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Fog
2
+ module Attributes
3
+ class String < Default
4
+ def create_setter
5
+ model.class_eval <<-EOS, __FILE__, __LINE__
6
+ def #{name}=(new_#{name})
7
+ attributes[:#{name}] = new_#{name}.to_s
8
+ end
9
+ EOS
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module Fog
2
+ module Attributes
3
+ class Time < Default
4
+ def create_setter
5
+ model.class_eval <<-EOS, __FILE__, __LINE__
6
+ def #{name}=(new_#{name})
7
+ attributes[:#{name}] = if new_#{name}.nil? || new_#{name} == "" || new_#{name}.is_a?(::Time)
8
+ new_#{name}
9
+ elsif new_#{name}.respond_to?(:to_time)
10
+ new_#{name}.to_time
11
+ else
12
+ ::Time.parse(new_#{name})
13
+ end
14
+ end
15
+ EOS
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Fog
2
+ module Attributes
3
+ class Timestamp < Default
4
+ def create_setter
5
+ model.class_eval <<-EOS, __FILE__, __LINE__
6
+ def #{name}=(new_#{name})
7
+ if new_#{name}.respond_to?(:to_i)
8
+ attributes[:#{name}] = Fog::Time.at(new_#{name}.to_i)
9
+ else
10
+ attributes[:#{name}] = Fog::Time.parse(new_#{name}.to_s)
11
+ end
12
+ end
13
+ EOS
14
+ end
15
+ end
16
+ end
17
+ end
@@ -16,6 +16,7 @@ module Fog
16
16
  # @option params [Hash<Symbol, String>] :headers The default headers to supply in a request. Only used if params[:headers] is not supplied to Connection#request
17
17
  # @option params [String] :host The destination host's reachable DNS name or IP, in the form of a String
18
18
  # @option params [String] :path Default path; appears after 'scheme://host:port/'. Only used if params[:path] is not supplied to Connection#request
19
+ # @option params [String] :path_prefix Sticky version of the "path" arg. :XSpath_prefix => "foo/bar" with a request with :path => "blech" sends a request to path "foo/bar/blech"
19
20
  # @option params [Fixnum] :port The port on which to connect, to the destination host
20
21
  # @option params [Hash] :query Default query; appended to the 'scheme://host:port/path/' in the form of '?key=value'. Will only be used if params[:query] is not supplied to Connection#request
21
22
  # @option params [String] :scheme The protocol; 'https' causes OpenSSL to be used
@@ -23,8 +24,15 @@ module Fog
23
24
  # @option params [Fixnum] :retry_limit Set how many times we'll retry a failed request. (Default 4)
24
25
  # @option params [Class] :instrumentor Responds to #instrument as in ActiveSupport::Notifications
25
26
  # @option params [String] :instrumentor_name Name prefix for #instrument events. Defaults to 'excon'
26
- #
27
27
  def initialize(url, persistent=false, params={})
28
+ if params[:path_prefix]
29
+ if params[:path]
30
+ raise ArgumentError, "optional arg 'path' is invalid when 'path_prefix' is provided"
31
+ end
32
+
33
+ @path_prefix = params.delete(:path_prefix)
34
+ end
35
+
28
36
  unless params.has_key?(:debug_response)
29
37
  params[:debug_response] = true
30
38
  end
@@ -53,7 +61,7 @@ module Fog
53
61
  # @raise [Excon::Errors::SocketError]
54
62
  #
55
63
  def request(params, &block)
56
- @excon.request(params, &block)
64
+ @excon.request(handle_path_prefix_for(params), &block)
57
65
  end
58
66
 
59
67
  # Make {#request} available even when it has been overidden by a subclass
@@ -67,6 +75,16 @@ module Fog
67
75
  def reset
68
76
  @excon.reset
69
77
  end
78
+
79
+ private
80
+
81
+ def handle_path_prefix_for(params)
82
+ return params unless @path_prefix
83
+
84
+ params[:path] = params[:path].sub(/^\//, "")
85
+ params[:path] = "#{@path_prefix}/#{params[:path]}"
86
+ params
87
+ end
70
88
  end
71
89
  end
72
90
  end
@@ -0,0 +1,27 @@
1
+ module Fog
2
+ module StringifyKeys
3
+
4
+ # Returns a new hash with all keys converted to strings.
5
+ def self.stringify(hash)
6
+ self.transform_hash(hash) {|hash, key, value|
7
+ hash[key.to_s] = value
8
+ }
9
+ end
10
+
11
+ private
12
+
13
+ # http://devblog.avdi.org/2009/11/20/hash-transforms-in-ruby/
14
+ def self.transform_hash(original, options={}, &block)
15
+ original.inject({}){|result, (key,value)|
16
+ value = if (options[:deep] && Hash === value)
17
+ transform_hash(value, options, &block)
18
+ else
19
+ value
20
+ end
21
+ block.call(result,key,value)
22
+ result
23
+ }
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ module Fog
2
+ module WhitelistKeys
3
+ def self.whitelist(hash, valid_keys)
4
+ valid_hash = StringifyKeys.stringify(hash)
5
+ valid_hash.select {|k,v| valid_keys.include?(k)}
6
+ end
7
+ end
8
+ end
@@ -14,10 +14,14 @@ module Fog
14
14
  else
15
15
  if self.providers.include?(provider)
16
16
  require "fog/#{provider}/dns"
17
- return Fog::DNS.const_get(Fog.providers[provider]).new(attributes)
17
+ begin
18
+ Fog::DNS.const_get(Fog.providers[provider])
19
+ rescue
20
+ Fog::const_get(Fog.providers[provider])::DNS
21
+ end.new(attributes)
22
+ else
23
+ raise ArgumentError.new("#{provider} is not a recognized dns provider")
18
24
  end
19
-
20
- raise ArgumentError.new("#{provider} is not a recognized dns provider")
21
25
  end
22
26
  end
23
27
 
@@ -17,7 +17,7 @@ module Fog
17
17
  begin
18
18
  Fog::Identity.const_get(Fog.providers[provider]).new(attributes)
19
19
  rescue
20
- Fog::const_get(Fog.providers[provider]).const_get("Identity").new(attributes)
20
+ Fog::const_get(Fog.providers[provider])::Identity.new(attributes)
21
21
  end
22
22
  end
23
23
 
@@ -1,3 +1,3 @@
1
1
  module Fog
2
- VERSION = "1.22.0"
2
+ VERSION = "1.23.0"
3
3
  end
@@ -30,4 +30,71 @@ describe Fog::Core::Connection do
30
30
  }
31
31
  Fog::Core::Connection.new("http://example.com", true, options)
32
32
  end
33
+
34
+ describe ":path_prefix" do
35
+ it "does not emit a warning when provided this argument in the initializer" do
36
+ $stderr = StringIO.new
37
+
38
+ Fog::Core::Connection.new("http://example.com", false, :path_prefix => "foo")
39
+
40
+ assert_empty($stderr.string)
41
+ end
42
+
43
+ it "raises when the 'path' arg is present and this arg is supplied" do
44
+ assert_raises(ArgumentError) do
45
+ Fog::Core::Connection.new("http://example.com", false, :path_prefix => "foo", :path => "bar")
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#request" do
51
+ describe "default behavior" do
52
+ it "supplies the 'path' arg directly to Excon" do
53
+ spy = Object.new
54
+ spy.instance_eval do
55
+ def params
56
+ @params
57
+ end
58
+ def new(_, params)
59
+ @params = params
60
+ end
61
+ end
62
+
63
+ Object.stub_const("Excon", spy) do
64
+ c = Fog::Core::Connection.new("http://example.com", false, :path => "bar")
65
+ assert_equal("bar", spy.params[:path])
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "with path_prefix supplied to the initializer" do
71
+ let(:spy) {
72
+ Object.new.tap { |spy|
73
+ spy.instance_eval do
74
+ def new(*args); self; end
75
+ def params; @params; end
76
+ def request(params)
77
+ @params = params
78
+ end
79
+ end
80
+ }
81
+ }
82
+
83
+ it "uses the initializer-supplied :path_prefix arg with #request :arg to formulate a path to send to Excon.request" do
84
+ Object.stub_const("Excon", spy) do
85
+ c = Fog::Core::Connection.new("http://example.com", false, :path_prefix => "foo")
86
+ c.request(:path => "bar")
87
+ assert_equal("foo/bar", spy.params[:path])
88
+ end
89
+ end
90
+
91
+ it "does not introduce consecutive '/'s into the path if 'path' starts with a '/'" do
92
+ Object.stub_const("Excon", spy) do
93
+ c = Fog::Core::Connection.new("http://example.com", false, :path_prefix => "foo")
94
+ c.request(:path => "/bar")
95
+ assert_equal("foo/bar", spy.params[:path])
96
+ end
97
+ end
98
+ end
99
+ end
33
100
  end
@@ -1,27 +1,39 @@
1
1
  require 'spec_helper'
2
+ require 'xmlrpc/datetime'
2
3
 
3
4
  class FogAttributeTestModel < Fog::Model
5
+ identity :id
4
6
  attribute :key, :aliases => "keys", :squash => "id"
5
7
  attribute :time, :type => :time
6
8
  attribute :bool, :type => :boolean
9
+ attribute :float, :type => :float
10
+ attribute :integer, :type => :integer
11
+ attribute :string, :type => :string
12
+ attribute :timestamp, :type => :timestamp
13
+ attribute :array, :type => :array
14
+ attribute :default, :default => 'default_value'
7
15
  end
8
16
 
9
17
  describe "Fog::Attributes" do
10
-
18
+
11
19
  let(:model) { FogAttributeTestModel.new }
12
20
 
21
+ it "should not create alias for nil" do
22
+ FogAttributeTestModel.aliases.must_equal({ "keys" => :key })
23
+ end
24
+
13
25
  describe "squash 'id'" do
14
26
  it "squashes if the key is a String" do
15
27
  model.merge_attributes("keys" => {:id => "value"})
16
28
  assert_equal"value", model.key
17
29
  end
18
-
30
+
19
31
  it "squashes if the key is a Symbol" do
20
32
  model.merge_attributes("keys" => {"id" => "value"})
21
33
  assert_equal "value", model.key
22
34
  end
23
35
  end
24
-
36
+
25
37
  describe ":type => time" do
26
38
  it "returns nil when provided nil" do
27
39
  model.merge_attributes(:time => nil)
@@ -38,6 +50,12 @@ describe "Fog::Attributes" do
38
50
  model.merge_attributes(:time => now.to_s)
39
51
  assert_equal Time.parse(now.to_s), model.time
40
52
  end
53
+
54
+ it "returns a Time object when passed a XMLRPC::DateTime object" do
55
+ now = XMLRPC::DateTime.new(2000, 7, 8, 10, 20, 34)
56
+ model.merge_attributes(:time => now)
57
+ assert_equal now.to_time, model.time
58
+ end
41
59
  end
42
60
 
43
61
  describe ":type => :boolean" do
@@ -66,4 +84,102 @@ describe "Fog::Attributes" do
66
84
  refute model.bool
67
85
  end
68
86
  end
87
+
88
+ describe ":type => :float" do
89
+ it "returns an integer as float" do
90
+ model.merge_attributes(:float => 1)
91
+ assert_in_delta 1.0, model.float
92
+ end
93
+
94
+ it "returns a string as float" do
95
+ model.merge_attributes(:float => '1')
96
+ assert_in_delta 1.0, model.float
97
+ end
98
+ end
99
+
100
+ describe ":type => :integer" do
101
+ it "returns a float as integer" do
102
+ model.merge_attributes(:integer => 1.5)
103
+ assert_in_delta 1, model.integer
104
+ end
105
+
106
+ it "returns a string as integer" do
107
+ model.merge_attributes(:integer => '1')
108
+ assert_in_delta 1, model.integer
109
+ end
110
+ end
111
+
112
+ describe ":type => :string" do
113
+ it "returns a float as string" do
114
+ model.merge_attributes(:string => 1.5)
115
+ assert_equal '1.5', model.string
116
+ end
117
+
118
+ it "returns a integer as string" do
119
+ model.merge_attributes(:string => 1)
120
+ assert_equal '1', model.string
121
+ end
122
+ end
123
+
124
+ describe ":type => :timestamp" do
125
+ it "returns a date as time" do
126
+ model.merge_attributes(:timestamp => Date.new(2008, 10, 12))
127
+ assert_equal '2008-10-12 00:00', model.timestamp.strftime('%Y-%m-%d %M:%S')
128
+ assert_instance_of Fog::Time, model.timestamp
129
+ end
130
+
131
+ it "returns a time as time" do
132
+ model.merge_attributes(:timestamp => Time.mktime(2007, 11, 1, 15, 25))
133
+ assert_equal '2007-11-01 25:00', model.timestamp.strftime('%Y-%m-%d %M:%S')
134
+ assert_instance_of Fog::Time, model.timestamp
135
+ end
136
+
137
+ it "returns a date_time as time" do
138
+ model.merge_attributes(:timestamp => DateTime.new(2007, 11, 1, 15, 25, 0))
139
+ assert_equal '2007-11-01 25:00', model.timestamp.strftime('%Y-%m-%d %M:%S')
140
+ assert_instance_of Fog::Time, model.timestamp
141
+ end
142
+ end
143
+
144
+ describe ":type => :array" do
145
+ it "returns an empty array as an empty array" do
146
+ model.merge_attributes(:array => [])
147
+ assert_equal [], model.array
148
+ end
149
+
150
+ it "returns a single element as array" do
151
+ model.merge_attributes(:array => 1.5)
152
+ assert_equal [ 1.5 ], model.array
153
+ end
154
+
155
+ it "returns an array as array" do
156
+ model.merge_attributes(:array => [ 1, 2 ])
157
+ assert_equal [ 1, 2 ], model.array
158
+ end
159
+ end
160
+
161
+ describe ":default => 'default_value'" do
162
+ it "should return nil when default is not defined on a new object" do
163
+ assert_equal model.bool, nil
164
+ end
165
+
166
+ it "should return the value of the object when default is not defined" do
167
+ model.merge_attributes({ :bool => false })
168
+ assert_equal model.bool, false
169
+ end
170
+
171
+ it "should return the default value on a new object" do
172
+ assert_equal model.default, 'default_value'
173
+ end
174
+
175
+ it "should return the value of the persisted object" do
176
+ model.merge_attributes({ :id => 'some-crazy-id', :default => 23 })
177
+ assert_equal model.default, 23
178
+ end
179
+
180
+ it "should return nil on a persisted object without a value" do
181
+ model.merge_attributes({ :id => 'some-crazy-id' })
182
+ assert_equal model.default, nil
183
+ end
184
+ end
69
185
  end
@@ -0,0 +1,29 @@
1
+ input_hash = {
2
+ :name => 'test-server',
3
+ :flavor => '123'
4
+ }
5
+
6
+ output_hash = {
7
+ 'name' => 'test-server',
8
+ 'flavor' => '123'
9
+ }
10
+
11
+ Shindo.tests('Fog::StringifyKeys', 'core') do
12
+
13
+ tests('keys') do
14
+
15
+ tests('stringifies symbols') do
16
+ returns(output_hash) {
17
+ Fog::StringifyKeys.stringify(input_hash)
18
+ }
19
+ end
20
+
21
+ tests('skips strings') do
22
+ returns(output_hash) {
23
+ Fog::StringifyKeys.stringify(output_hash)
24
+ }
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,24 @@
1
+ input_hash = {
2
+ :name => 'test-server',
3
+ :flavor => '123',
4
+ :size => '12345'
5
+ }
6
+
7
+ output_hash = {
8
+ 'name' => 'test-server',
9
+ 'flavor' => '123'
10
+ }
11
+
12
+ valid_keys = %w{flavor name}
13
+
14
+ Shindo.tests('Fog::WhitelistKeys', 'core') do
15
+
16
+ tests('whitelist_keys') do
17
+ tests('excludes invalid values') do
18
+ returns(output_hash) {
19
+ Fog::WhitelistKeys.whitelist(input_hash, valid_keys)
20
+ }
21
+ end
22
+ end
23
+
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.22.0
4
+ version: 1.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Light
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-17 00:00:00.000000000 Z
12
+ date: 2014-07-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: builder
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - ~>
33
33
  - !ruby/object:Gem::Version
34
- version: '0.33'
34
+ version: '0.38'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ~>
40
40
  - !ruby/object:Gem::Version
41
- version: '0.33'
41
+ version: '0.38'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: formatador
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -219,6 +219,14 @@ files:
219
219
  - lib/fog/compute/models/server.rb
220
220
  - lib/fog/core.rb
221
221
  - lib/fog/core/attributes.rb
222
+ - lib/fog/core/attributes/array.rb
223
+ - lib/fog/core/attributes/boolean.rb
224
+ - lib/fog/core/attributes/default.rb
225
+ - lib/fog/core/attributes/float.rb
226
+ - lib/fog/core/attributes/integer.rb
227
+ - lib/fog/core/attributes/string.rb
228
+ - lib/fog/core/attributes/time.rb
229
+ - lib/fog/core/attributes/timestamp.rb
222
230
  - lib/fog/core/collection.rb
223
231
  - lib/fog/core/connection.rb
224
232
  - lib/fog/core/credentials.rb
@@ -234,11 +242,13 @@ files:
234
242
  - lib/fog/core/scp.rb
235
243
  - lib/fog/core/service.rb
236
244
  - lib/fog/core/ssh.rb
245
+ - lib/fog/core/stringify_keys.rb
237
246
  - lib/fog/core/time.rb
238
247
  - lib/fog/core/utils.rb
239
248
  - lib/fog/core/uuid.rb
240
249
  - lib/fog/core/wait_for.rb
241
250
  - lib/fog/core/wait_for_defaults.rb
251
+ - lib/fog/core/whitelist_keys.rb
242
252
  - lib/fog/dns.rb
243
253
  - lib/fog/identity.rb
244
254
  - lib/fog/image.rb
@@ -280,6 +290,8 @@ files:
280
290
  - spec/utils_spec.rb
281
291
  - spec/uuid_spec.rb
282
292
  - spec/wait_for_spec.rb
293
+ - tests/core/stringify_keys_tests.rb
294
+ - tests/core/whitelist_keys_tests.rb
283
295
  homepage: https://github.com/fog/fog-core
284
296
  licenses:
285
297
  - MIT
@@ -300,7 +312,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
300
312
  version: '0'
301
313
  requirements: []
302
314
  rubyforge_project:
303
- rubygems_version: 2.2.2
315
+ rubygems_version: 2.3.0
304
316
  signing_key:
305
317
  specification_version: 4
306
318
  summary: Shared classes and tests for fog providers and services.