ironfan 6.1.5 → 6.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'bundler/gem_tasks'
2
2
 
3
3
  require 'rspec/core/rake_task'
4
4
  RSpec::Core::RakeTask.new(:spec) do |spec|
5
- spec.pattern = 'spec/{ironfan,chef,ironfan/*}/*_spec.rb'
5
+ spec.pattern = 'spec/{gorillib,ironfan,chef,ironfan/*}/*_spec.rb'
6
6
  end
7
7
 
8
8
  desc 'Run RSpec code examples with SimpleCov'
@@ -80,6 +80,12 @@ module Gorillib
80
80
  self
81
81
  end
82
82
 
83
+ # @param field_name [String or Symbol]
84
+ #
85
+ # This is one of two methods used to resolve Gorillib
86
+ # collections. (The other is merge_resolve.) It simply resolves
87
+ # the field and returns the result. In case the field is a
88
+ # gorillib collection, it resolves each item in the collection.
83
89
  def deep_resolve(field_name)
84
90
  temp = read_set_or_underlay_attribute(field_name)
85
91
  return if temp.nil?
@@ -87,7 +93,7 @@ module Gorillib
87
93
  result = temp.class.new
88
94
  temp.each_pair {|k,v| result[k] = resolve_value(v) }
89
95
  else
90
- result = resolve_value(v)
96
+ result = resolve_value(result)
91
97
  end
92
98
  result
93
99
  end
@@ -98,6 +104,12 @@ module Gorillib
98
104
  deep_copy(value)
99
105
  end
100
106
 
107
+ # @param field_name [String or Symbol]
108
+ #
109
+ # This is one of two methods used to resolve Gorillib
110
+ # collections. (The other is deep_resolve.) It returns the result
111
+ # of merging the value of a field with the value of that field on
112
+ # the parent (underlay) of this object.
101
113
  def merge_resolve(field_name)
102
114
  field = self.class.fields[field_name] or return
103
115
  result = field.type.new
@@ -106,6 +118,20 @@ module Gorillib
106
118
  result
107
119
  end
108
120
 
121
+ # @param target [Gorillib::Model]
122
+ # @param value [Gorillib::Model]
123
+ #
124
+ # This method makes the assumption that target and value are both
125
+ # instances of either Gorillib::Model or
126
+ # Gorillib::Collection. They should be the same type.
127
+ #
128
+ # This method is called for its side-effects on the 'target'
129
+ # parameter.
130
+ #
131
+ # In case they are both models, target.receive!(value) is called.
132
+ #
133
+ # In case they are both collections, target[k].receive!(v) is
134
+ # called, for each k,v in value.
109
135
  def merge_values(target, value=nil)
110
136
  value ||= {}
111
137
  if target.is_a? Gorillib::Collection
@@ -474,7 +474,7 @@ Chef::Config[:ec2_image_info].merge!({
474
474
  # Precise (Ubuntu 11.10)
475
475
  #
476
476
  %w[ us-east-1 32-bit ebs precise ] => { :image_id => 'ami-3b4ff252', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
477
- %w[ us-east-1 64-bit ebs precise ] => { :image_id => 'ami-3d4ff254', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
477
+ %w[ us-east-1 64-bit ebs precise ] => { :image_id => 'ami-5db4a934', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
478
478
  %w[ us-west-2 32-bit ebs precise ] => { :image_id => 'ami-7cab224c', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
479
479
  %w[ us-west-2 64-bit ebs precise ] => { :image_id => 'ami-7eab224e', :ssh_user => 'ubuntu', :bootstrap_distro => "ubuntu10.04-gems", },
480
480
  # # These images will only work once http://askubuntu.com/questions/209844/latest-ec2-ubuntu-instance-seems-broken is fixed
@@ -5,7 +5,30 @@ module Ironfan
5
5
  field :group_authorized, Array, :default => []
6
6
  field :group_authorized_by, Array, :default => []
7
7
  field :range_authorizations, Array, :default => []
8
-
8
+
9
+ # This allows Gorillib resolution to merge-resolve a collection
10
+ # of security groups and properly merge authorizations.
11
+ def receive!(hsh, &blk)
12
+ if hsh.respond_to? :attributes
13
+ hsh = hsh.attributes
14
+ end
15
+ super(hsh.merge({
16
+ group_authorized: (
17
+ group_authorized +
18
+ hsh.delete(:group_authorized).to_a +
19
+ hsh.delete('group_authorized').to_a).uniq,
20
+ group_authorized_by: (
21
+ group_authorized_by +
22
+ hsh.delete(:group_authorized_by).to_a +
23
+ hsh.delete('group_authorized_by').to_a).uniq,
24
+ range_authorizations: (
25
+ range_authorizations +
26
+ hsh.delete(:range_authorizations).to_a +
27
+ hsh.delete('range_authorizations').to_a).uniq,
28
+ }),
29
+ &blk)
30
+ end
31
+
9
32
  def authorize_port_range(range, cidr_ip = '0.0.0.0/0', ip_protocol = 'tcp')
10
33
  range = (range .. range) if range.is_a?(Integer)
11
34
  range_authorizations << [range, cidr_ip, ip_protocol]
@@ -1,3 +1,3 @@
1
1
  module Ironfan
2
- VERSION = '6.1.5'
2
+ VERSION = '6.1.6'
3
3
  end
@@ -0,0 +1,202 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ironfan::Dsl, resolution: true do
4
+ it 'merges collections' do
5
+ dmx = DMX.new do
6
+ mx :x1
7
+ dmx(:dmx) do
8
+ mx :x2
9
+ end
10
+ end
11
+
12
+ # This will deep-resolve the dmxs collection, which will
13
+ # merge-resolve the mxs collection.
14
+
15
+ dmx.resolve!
16
+ dmx.dmx(:dmx).mxs.keys.map(&:to_s).sort.should == %w[ x1 x2 ]
17
+ end
18
+
19
+ it 'deep resolves collections when requested' do
20
+ ddx = DDX.new do
21
+ dx :x1
22
+ ddx(:ddx) do
23
+ dx :x2
24
+ end
25
+ end
26
+
27
+ # This will deep-resolve the ddxs collection, which will
28
+ # deep-resolve the dxs collection. Because there is a dxs
29
+ # collection set, this will simply ignore the parent dxs
30
+ # collection.
31
+
32
+ ddx.resolve!
33
+ ddx.ddx(:ddx).dxs.keys.map(&:to_s).sort.should == %w[ x2 ]
34
+ end
35
+
36
+ it 'deep resolves collections when requested and no default is available' do
37
+ ddx = DDX.new do
38
+ dx :x1
39
+ ddx(:ddx) do
40
+ end
41
+ end
42
+
43
+ # This will deep-resolve the ddxs collection, which will
44
+ # deep-resolve the dxs collection. Because there is no dxs
45
+ # collection set,this will pull in the parent dxx collection.
46
+
47
+ ddx.resolve!
48
+ ddx.ddx(:ddx).dxs.keys.map(&:to_s).sort.should == %w[ x1 ]
49
+ end
50
+
51
+ it 'does not resolve when merging' do
52
+ mdx = MDX.new do
53
+ dx :x1
54
+ mdx(:mdx) do
55
+ dx :x2
56
+ end
57
+ end
58
+
59
+ # This will merge the mdxs collection with nothing.
60
+
61
+ mdx.resolve!
62
+ mdx.mdx(:mdx).dxs.keys.map(&:to_s).sort.should == %w[ x2 ]
63
+ end
64
+
65
+ it 'does not resolve when merging, not even merge resolve' do
66
+ mmx = MMX.new do
67
+ mx :x1
68
+ mmx(:mmx) do
69
+ mx :x2
70
+ end
71
+ end
72
+
73
+ # This will merge the mmxs collection with nothing. The mmxs
74
+ # collection will not be resolved, so its mxs collection will not
75
+ # be merged with its parent.
76
+
77
+ mmx.resolve!
78
+ mmx.mmx(:mmx).mxs.keys.map(&:to_s).sort.should == %w[ x2 ]
79
+ end
80
+
81
+ it 'does not merge when deep-resolving' do
82
+ ddmx = DDMX.new do
83
+ dmx :dmx do
84
+ mx :x1
85
+ end
86
+ ddmx(:ddmx) do
87
+ dmx :dmx do
88
+ mx :x2
89
+ end
90
+ end
91
+ end
92
+ ddmx.resolve!
93
+
94
+ # This is surprising behavior, but consistent with Ironfan's
95
+ # interface. Because the dmxs collection on the :ddmx object is
96
+ # deep-resolved rather than merge-resolved, its parent is ignored.
97
+
98
+ ddmx.ddmx(:ddmx).dmx(:dmx).mxs.keys.map(&:to_s).sort.should == %w[ x2 ]
99
+ end
100
+
101
+ it 'merges collections deeply' do
102
+ dmmx = DMMX.new do
103
+ mmx :mmx do
104
+ mx :x1
105
+ end
106
+ dmmx(:dmmx) do
107
+ mmx :mmx do
108
+ mx :x2
109
+ end
110
+ end
111
+ end
112
+ dmmx.resolve!
113
+
114
+ # Deep resolve at the top level causes the dmmxs collection to be
115
+ # resolved. It resolves all of its fields, including the mmx
116
+ # field, which is merge-resolved.
117
+
118
+ dmmx.dmmx(:dmmx).mmx(:mmx).mxs.keys.map(&:to_s).sort.should == %w[ x1 x2 ]
119
+ end
120
+
121
+ it 'does not merge collections very deeply' do
122
+ dmmmx = DMMMX.new do
123
+ mmmx :mmmx do
124
+ mmx :mmx do
125
+ mx :x1
126
+ end
127
+ end
128
+ dmmmx(:dmmmx) do
129
+ mmmx :mmmx do
130
+ mmx :mmx do
131
+ mx :x2
132
+ end
133
+ end
134
+ end
135
+ end
136
+ dmmmx.resolve!
137
+
138
+ # FIXME: Shouldn't this be both x1 and x2? I'm going to place this
139
+ # here to test the interface as it exists now.
140
+
141
+ dmmmx.dmmmx(:dmmmx).mmmx(:mmmx).mmx(:mmx).mxs.keys.map(&:to_s).sort.should == %w[ x2 ]
142
+ end
143
+
144
+ it 'ignores resolution strategies when merging' do
145
+ dmdx = DMDX.new do
146
+ mdx :mdx do
147
+ dx :x1
148
+ end
149
+ dmdx(:dmdx) do
150
+ mdx :mdx do
151
+ dx :x2
152
+ end
153
+ end
154
+ end
155
+ dmdx.resolve!
156
+
157
+ # Deep resolve at the top level causes the dmdxs collection to be
158
+ # resolved. It resolves all of its fields, including the mdx
159
+ # field, which is merge-resolved. Note that resolve! does the rest
160
+ # of the work: the merge_resolve method does not recursively
161
+ # resolve, so the dxs "deep resolve" resolution strategy is
162
+ # ignored.
163
+
164
+ dmdx.dmdx(:dmdx).mdx(:mdx).dxs.keys.map(&:to_s).sort.should == %w[ x1 x2 ]
165
+ end
166
+
167
+ it 'should not raise exceptions when deep-resolving non-collections' do
168
+ class Kablooey < Ironfan::Dsl
169
+ magic :foo, String, :resolver => :deep_resolve
170
+ end
171
+
172
+ Kablooey.new(foo: 'bar').resolve!
173
+ end
174
+
175
+ it 'may rely on receive! to do a somewhat deep merge, because it does' do
176
+ a = MX.new do
177
+ mx :one
178
+ end
179
+ b = MX.new do
180
+ mx :two
181
+ end
182
+
183
+ a.receive! b
184
+ a.mxs.keys.map(&:to_s).sort.should == %w[ one two ]
185
+ end
186
+
187
+ it 'does not rely on receive! to do a very deep merge, because it does not' do
188
+ a = MMX.new do
189
+ mmx :mmx do
190
+ mx :one
191
+ end
192
+ end
193
+ b = MMX.new do
194
+ mmx :mmx do
195
+ mx :two
196
+ end
197
+ end
198
+
199
+ a.receive! b
200
+ a.mmx(:mmx).mxs.keys.map(&:to_s).sort.should == %w[ two ]
201
+ end
202
+ end
@@ -21,4 +21,52 @@ describe Ironfan::Dsl::Cluster do
21
21
  "role[is_last]"
22
22
  ]
23
23
  }
24
+
25
+ context 'when merging security groups' do
26
+ let (:secg) do
27
+ Ironfan.cluster :merge_sec_group do
28
+ security_group('s_cli').authorized_by_group('s_serv_cluster')
29
+ facet(:f) do
30
+ security_group('s_cli').authorized_by_group('s_serv_facet')
31
+ end
32
+ end
33
+ end
34
+
35
+ it 'merges all of its security groups appropriately' do
36
+ secg.
37
+ facet(:f).
38
+ security_group('s_cli').
39
+ group_authorized_by.sort.should == %w[ s_serv_cluster s_serv_facet ]
40
+ end
41
+ end
42
+
43
+ context 'when merging security groups' do
44
+ let (:cloud_secg) do
45
+ Ironfan::Dsl::Cluster.new(:merge_sec_group) do
46
+ cloud(:ec2).security_group('s_cli').authorized_by_group('s_serv_cluster')
47
+ facet(:f) do
48
+ cloud(:ec2).security_group('s_cli').authorized_by_group('s_serv_facet')
49
+ end
50
+ end.tap(&:resolve!)
51
+ end
52
+
53
+ it 'merges all of its cloud security groups appropriately' do
54
+ pending('fixes to apparent design flaw in Ironfan/Gorillib resolution')
55
+ cloud_secg.
56
+ facet(:f).
57
+ cloud(:ec2).
58
+ security_group('s_cli').
59
+ group_authorized_by.sort.should == %w[ s_serv_cluster s_serv_facet ]
60
+ end
61
+ end
62
+
63
+ context 'with security groups' do
64
+ let (:auth_a) { Ironfan::Dsl::SecurityGroup.new{ authorized_by_group('a') } }
65
+ let (:auth_b) { Ironfan::Dsl::SecurityGroup.new{ authorized_by_group('b') } }
66
+
67
+ it 'should correctly merge them' do
68
+ auth_a.receive!(auth_b)
69
+ auth_a.group_authorized_by.sort.should == %w[ a b ]
70
+ end
71
+ end
24
72
  end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ironfan::Dsl::Ec2 do
4
+ context 'with cloud-level security groups' do
5
+ let (:cloud_a) { Ironfan::Dsl::Ec2.new{ security_group('s').authorized_by_group('a') } }
6
+ let (:cloud_b) { Ironfan::Dsl::Ec2.new{ security_group('s').authorized_by_group('b') } }
7
+
8
+ it 'should correctly merge them' do
9
+ pending('fixes to apparent design bugs in Ironfan/Gorillib resolution')
10
+
11
+ cloud_a.receive! cloud_b
12
+ cloud_a.security_group('s').group_authorized_by.sort.should == %w[ a b ]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ironfan::Dsl::SecurityGroup do
4
+ context 'with security groups' do
5
+ let (:auth_a) { Ironfan::Dsl::SecurityGroup.new{ authorized_by_group('a') } }
6
+ let (:auth_b) { Ironfan::Dsl::SecurityGroup.new{ authorized_by_group('b') } }
7
+
8
+ it 'should correctly merge them' do
9
+ auth_a.receive!(auth_b)
10
+ auth_a.group_authorized_by.sort.should == %w[ a b ]
11
+ end
12
+ end
13
+ end
@@ -37,3 +37,5 @@ end
37
37
  require 'chef_zero/server'
38
38
  server = ChefZero::Server.new(port: 4000)
39
39
  server.start_background
40
+
41
+ require_relative 'support/resolution'
@@ -0,0 +1,63 @@
1
+ shared_context :resolution, resolution: true do
2
+ module ResolutionHelpers
3
+ def initialize(attrs = {}, &blk)
4
+ self.underlay = attrs.delete(:owner)
5
+ super(attrs, &blk)
6
+ end
7
+ end
8
+
9
+ class X < Ironfan::Dsl
10
+ include ResolutionHelpers
11
+ magic :name, Symbol
12
+ magic :dat, Integer
13
+ end
14
+
15
+ class MSym < Ironfan::Dsl
16
+ include ResolutionHelpers
17
+ magic :name, Symbol, :resolver => :merge_resolve, key_method: :name
18
+ end
19
+
20
+ class MX < X
21
+ collection :mxs, X, :resolver => :merge_resolve, key_method: :name
22
+ end
23
+
24
+ class DX < X
25
+ collection :dxs, X, :resolver => :deep_resolve, key_method: :name
26
+ end
27
+
28
+ class DMX < MX
29
+ collection :dmxs, MX, :resolver => :deep_resolve, key_method: :name
30
+ end
31
+
32
+ class DDX < DX
33
+ collection :ddxs, DX, :resolver => :deep_resolve, key_method: :name
34
+ end
35
+
36
+ class MDX < DX
37
+ collection :mdxs, DX, :resolver => :merge_resolve, key_method: :name
38
+ end
39
+
40
+ class MMX < MX
41
+ collection :mmxs, MX, :resolver => :merge_resolve, key_method: :name
42
+ end
43
+
44
+ class DDMX < DMX
45
+ collection :ddmxs, DMX, :resolver => :deep_resolve, key_method: :name
46
+ end
47
+
48
+ class DMMX < MMX
49
+ collection :dmmxs, MMX, :resolver => :deep_resolve, key_method: :name
50
+ end
51
+
52
+ class MMMX < MMX
53
+ collection :mmmxs, MMX, :resolver => :merge_resolve, key_method: :name
54
+ end
55
+
56
+ class DMDX < MDX
57
+ collection :dmdxs, MDX, :resolver => :deep_resolve, key_method: :name
58
+ end
59
+
60
+ class DMMMX < MMMX
61
+ collection :dmmmxs, MMMX, :resolver => :deep_resolve, key_method: :name
62
+ end
63
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ironfan
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.5
4
+ version: 6.1.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-24 00:00:00.000000000 Z
12
+ date: 2014-05-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chef
@@ -271,6 +271,7 @@ files:
271
271
  - spec/fixtures/gunbai_slice.json
272
272
  - spec/fixtures/knife/knife.rb
273
273
  - spec/fixtures/realms/samurai.rb
274
+ - spec/gorillib/resolution_spec.rb
274
275
  - spec/integration/minimal-chef-repo/chefignore
275
276
  - spec/integration/minimal-chef-repo/clusters/.gitkeep
276
277
  - spec/integration/minimal-chef-repo/config/.gitkeep
@@ -297,12 +298,15 @@ files:
297
298
  - spec/ironfan/ec2/cloud_provider_spec.rb
298
299
  - spec/ironfan/ec2/elb_spec.rb
299
300
  - spec/ironfan/ec2/security_group_spec.rb
301
+ - spec/ironfan/ec2_spec.rb
300
302
  - spec/ironfan/manifest_spec.rb
301
303
  - spec/ironfan/plugin_spec.rb
302
304
  - spec/ironfan/realm_spec.rb
305
+ - spec/ironfan/security_group_spec.rb
303
306
  - spec/spec_helper.rb
304
307
  - spec/support/dummy_chef.rb
305
308
  - spec/support/dummy_diff_drawer.rb
309
+ - spec/support/resolution.rb
306
310
  homepage: http://infochimps.com/labs
307
311
  licenses:
308
312
  - apachev2
@@ -318,7 +322,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
318
322
  version: '0'
319
323
  segments:
320
324
  - 0
321
- hash: -1549978331265274060
325
+ hash: 4249485048014092893
322
326
  required_rubygems_version: !ruby/object:Gem::Requirement
323
327
  none: false
324
328
  requirements:
@@ -327,7 +331,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
327
331
  version: '0'
328
332
  segments:
329
333
  - 0
330
- hash: -1549978331265274060
334
+ hash: 4249485048014092893
331
335
  requirements: []
332
336
  rubyforge_project:
333
337
  rubygems_version: 1.8.25
@@ -342,6 +346,7 @@ test_files:
342
346
  - spec/fixtures/gunbai_slice.json
343
347
  - spec/fixtures/knife/knife.rb
344
348
  - spec/fixtures/realms/samurai.rb
349
+ - spec/gorillib/resolution_spec.rb
345
350
  - spec/integration/minimal-chef-repo/chefignore
346
351
  - spec/integration/minimal-chef-repo/clusters/.gitkeep
347
352
  - spec/integration/minimal-chef-repo/config/.gitkeep
@@ -368,10 +373,13 @@ test_files:
368
373
  - spec/ironfan/ec2/cloud_provider_spec.rb
369
374
  - spec/ironfan/ec2/elb_spec.rb
370
375
  - spec/ironfan/ec2/security_group_spec.rb
376
+ - spec/ironfan/ec2_spec.rb
371
377
  - spec/ironfan/manifest_spec.rb
372
378
  - spec/ironfan/plugin_spec.rb
373
379
  - spec/ironfan/realm_spec.rb
380
+ - spec/ironfan/security_group_spec.rb
374
381
  - spec/spec_helper.rb
375
382
  - spec/support/dummy_chef.rb
376
383
  - spec/support/dummy_diff_drawer.rb
384
+ - spec/support/resolution.rb
377
385
  has_rdoc: