ironfan 6.1.5 → 6.1.6

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.
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: