ironfan 5.0.11 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/.gitignore +4 -0
  2. data/.gitmodules +3 -0
  3. data/Gemfile +8 -26
  4. data/Gemfile.lock +38 -41
  5. data/NOTES-REALM.md +172 -0
  6. data/Rakefile +19 -77
  7. data/config/ubuntu12.04-ironfan.erb +7 -0
  8. data/ironfan.gemspec +28 -225
  9. data/lib/chef/cluster_knife.rb +26 -0
  10. data/lib/chef/knife/bootstrap/ubuntu12.04-ironfan.erb +7 -0
  11. data/lib/chef/knife/cluster_bootstrap.rb +1 -3
  12. data/lib/chef/knife/cluster_diff.rb +2 -8
  13. data/lib/chef/knife/cluster_kick.rb +1 -3
  14. data/lib/chef/knife/cluster_kill.rb +1 -2
  15. data/lib/chef/knife/cluster_launch.rb +17 -34
  16. data/lib/chef/knife/cluster_list.rb +6 -5
  17. data/lib/chef/knife/cluster_proxy.rb +1 -3
  18. data/lib/chef/knife/cluster_pry.rb +1 -2
  19. data/lib/chef/knife/cluster_show.rb +6 -7
  20. data/lib/chef/knife/cluster_ssh.rb +10 -8
  21. data/lib/chef/knife/cluster_start.rb +1 -2
  22. data/lib/chef/knife/cluster_stop.rb +1 -2
  23. data/lib/chef/knife/cluster_sync.rb +2 -3
  24. data/lib/chef/knife/ironfan_knife_common.rb +58 -18
  25. data/lib/chef/knife/ironfan_script.rb +0 -3
  26. data/lib/ironfan/broker/computer.rb +14 -11
  27. data/lib/ironfan/broker.rb +17 -12
  28. data/lib/ironfan/cookbook_requirements.rb +155 -0
  29. data/lib/ironfan/dsl/cloud.rb +2 -0
  30. data/lib/ironfan/dsl/cluster.rb +25 -15
  31. data/lib/ironfan/dsl/component.rb +12 -15
  32. data/lib/ironfan/dsl/compute.rb +10 -8
  33. data/lib/ironfan/dsl/ec2.rb +2 -26
  34. data/lib/ironfan/dsl/facet.rb +16 -14
  35. data/lib/ironfan/dsl/openstack.rb +147 -0
  36. data/lib/ironfan/dsl/realm.rb +23 -16
  37. data/lib/ironfan/dsl/security_group.rb +29 -0
  38. data/lib/ironfan/dsl/server.rb +14 -5
  39. data/lib/ironfan/dsl/static.rb +63 -0
  40. data/lib/ironfan/dsl/vsphere.rb +1 -0
  41. data/lib/ironfan/dsl.rb +1 -134
  42. data/lib/ironfan/headers.rb +19 -0
  43. data/lib/ironfan/provider/chef/node.rb +3 -2
  44. data/lib/ironfan/provider/ec2/machine.rb +10 -14
  45. data/lib/ironfan/provider/ec2/security_group.rb +58 -43
  46. data/lib/ironfan/provider/openstack/elastic_ip.rb +96 -0
  47. data/lib/ironfan/provider/openstack/keypair.rb +78 -0
  48. data/lib/ironfan/provider/openstack/machine.rb +371 -0
  49. data/lib/ironfan/provider/openstack/security_group.rb +224 -0
  50. data/lib/ironfan/provider/openstack.rb +69 -0
  51. data/lib/ironfan/provider/static/machine.rb +192 -0
  52. data/lib/ironfan/provider/static.rb +23 -0
  53. data/lib/ironfan/provider.rb +58 -1
  54. data/lib/ironfan/requirements.rb +17 -1
  55. data/lib/ironfan/version.rb +3 -0
  56. data/lib/ironfan.rb +107 -172
  57. data/spec/chef/cluster_bootstrap_spec.rb +2 -7
  58. data/spec/chef/cluster_launch_spec.rb +1 -2
  59. data/spec/fixtures/realms/samurai.rb +26 -0
  60. data/spec/integration/minimal-chef-repo/clusters/.gitkeep +0 -0
  61. data/spec/integration/minimal-chef-repo/config/.gitkeep +0 -0
  62. data/spec/integration/minimal-chef-repo/knife/credentials/.gitignore +1 -0
  63. data/spec/integration/minimal-chef-repo/knife/credentials/certificates/.gitkeep +0 -0
  64. data/spec/integration/minimal-chef-repo/knife/credentials/client_keys/.gitkeep +0 -0
  65. data/spec/integration/minimal-chef-repo/knife/credentials/data_bag_keys/.gitkeep +0 -0
  66. data/spec/integration/minimal-chef-repo/knife/credentials/ec2_certs/.gitkeep +0 -0
  67. data/spec/integration/minimal-chef-repo/knife/credentials/ec2_keys/.gitkeep +0 -0
  68. data/spec/integration/minimal-chef-repo/knife/credentials/ironfantest-validator.pem +27 -0
  69. data/spec/integration/minimal-chef-repo/knife/credentials/ironfantester.pem +27 -0
  70. data/spec/integration/minimal-chef-repo/tasks/.gitkeep +0 -0
  71. data/spec/ironfan/cluster_spec.rb +1 -2
  72. data/spec/ironfan/diff_spec.rb +0 -2
  73. data/spec/ironfan/dsl_spec.rb +6 -3
  74. data/spec/ironfan/ec2/cloud_provider_spec.rb +17 -18
  75. data/spec/ironfan/ec2/elb_spec.rb +44 -41
  76. data/spec/ironfan/ec2/security_group_spec.rb +45 -47
  77. data/spec/ironfan/manifest_spec.rb +0 -1
  78. data/spec/ironfan/plugin_spec.rb +55 -40
  79. data/spec/ironfan/realm_spec.rb +42 -30
  80. data/spec/spec_helper.rb +17 -31
  81. data/spec/{spec_helper → support}/dummy_chef.rb +0 -0
  82. data/spec/{spec_helper → support}/dummy_diff_drawer.rb +0 -0
  83. metadata +78 -155
  84. data/.rspec +0 -2
  85. data/.yardopts +0 -19
  86. data/VERSION +0 -2
  87. data/chefignore +0 -41
  88. data/notes/Future-development-proposals.md +0 -266
  89. data/notes/Home.md +0 -55
  90. data/notes/INSTALL-cloud_setup.md +0 -103
  91. data/notes/INSTALL.md +0 -134
  92. data/notes/Ironfan-Roadmap.md +0 -70
  93. data/notes/Upgrading-to-v4.md +0 -66
  94. data/notes/advanced-superpowers.md +0 -16
  95. data/notes/aws_servers.jpg +0 -0
  96. data/notes/aws_user_key.png +0 -0
  97. data/notes/cookbook-versioning.md +0 -11
  98. data/notes/core_concepts.md +0 -200
  99. data/notes/declaring_volumes.md +0 -3
  100. data/notes/design_notes-aspect_oriented_devops.md +0 -36
  101. data/notes/design_notes-ci_testing.md +0 -169
  102. data/notes/design_notes-cookbook_event_ordering.md +0 -249
  103. data/notes/design_notes-meta_discovery.md +0 -59
  104. data/notes/ec2-pricing_and_capacity.md +0 -75
  105. data/notes/ec2-pricing_and_capacity.numbers +0 -0
  106. data/notes/homebase-layout.txt +0 -102
  107. data/notes/knife-cluster-commands.md +0 -21
  108. data/notes/named-cloud-objects.md +0 -11
  109. data/notes/opscode_org_key.png +0 -0
  110. data/notes/opscode_user_key.png +0 -0
  111. data/notes/philosophy.md +0 -13
  112. data/notes/rake_tasks.md +0 -24
  113. data/notes/renamed-recipes.txt +0 -142
  114. data/notes/silverware.md +0 -85
  115. data/notes/style_guide.md +0 -300
  116. data/notes/tips_and_troubleshooting.md +0 -92
  117. data/notes/walkthrough-hadoop.md +0 -168
  118. data/notes/walkthrough-web.md +0 -166
  119. data/spec/fixtures/gunbai.rb +0 -24
  120. data/spec/test_config.rb +0 -20
  121. data/tasks/chef_config.rake +0 -38
@@ -1,5 +1,3 @@
1
- require 'chef/knife'
2
-
3
1
  module Ironfan
4
2
  module KnifeCommon
5
3
  attr_accessor :broker
@@ -16,10 +14,11 @@ module Ironfan
16
14
  $LOAD_PATH << File.join(Chef::Config[:ironfan_path], '/lib') if Chef::Config[:ironfan_path]
17
15
  require 'ironfan'
18
16
  $stdout.sync = true
19
- Ironfan.ui = self.ui
20
- self.config[:cloud] = Chef::Config[:cloud] if Chef::Config.has_key?(:cloud)
21
- Ironfan.chef_config = self.config
22
- self.broker = Ironfan.broker
17
+ Ironfan.ui = self.ui
18
+ self.config[:cloud] = Chef::Config[:cloud] if Chef::Config.has_key?(:cloud)
19
+ Ironfan.knife_config = self.config
20
+ Ironfan.chef_config = Chef::Config
21
+ self.broker = Ironfan.broker
23
22
  end
24
23
 
25
24
  def run()
@@ -51,21 +50,27 @@ module Ironfan
51
50
  #
52
51
  # @return [Ironfan::ServerSlice] the requested slice
53
52
  def get_slice(slice_string, *args)
54
- cluster_name, facet_name, slice_indexes = pick_apart(slice_string, *args)
55
- desc = predicate_str(cluster_name, facet_name, slice_indexes)
53
+ realm_name, cluster_name, facet_name, slice_indexes = pick_apart(slice_string, *args)
54
+ desc = predicate_str(realm_name, cluster_name, facet_name, slice_indexes)
56
55
  #
57
56
  ui.info("Inventorying servers in #{desc}")
58
- cluster = Ironfan.load_cluster(cluster_name)
59
- Chef::Config[:knife][:region] = cluster.servers.to_a.first.cloud(:ec2).region
60
- computers = broker.discover! cluster
57
+ realm = Ironfan.load_realm(realm_name)
58
+ realm.clusters.each{ |cluster| Ironfan.load_cluster cluster.name }
59
+ realm.resolve!
60
+ Chef::Config[:knife][:region] = realm.clusters.to_a.first.servers.to_a.first.cloud(:ec2).region
61
+ computers = broker.discover!(realm.clusters.to_a, config[:cloud])
61
62
  Chef::Log.info("Inventoried #{computers.size} computers")
62
63
  #
63
- computers.slice(facet_name, slice_indexes)
64
+ computers.slice(cluster_name, facet_name, slice_indexes)
64
65
  end
65
66
 
66
67
  def all_computers(slice_string, *args)
67
- cluster_name, facet_name, slice_indexes = pick_apart(slice_string, *args)
68
- computers = broker.discover! Ironfan.load_cluster(cluster_name)
68
+ realm_name, cluster_name, facet_name, slice_indexes = pick_apart(slice_string, *args)
69
+ realm = Ironfan.load_realm(realm_name)
70
+ realm.clusters.each{ |cluster| Ironfan.load_cluster cluster.name }
71
+ realm.resolve!
72
+ clusters = cluster_name ? Array(realm.clusters[cluster_name.to_sym]) : realm.clusters.to_a
73
+ computers = broker.discover!(clusters, config[:cloud])
69
74
  ui.info("Loaded information for #{computers.size} computer(s) in cluster #{cluster_name}")
70
75
  computers
71
76
  end
@@ -76,11 +81,12 @@ module Ironfan
76
81
  ui.info("")
77
82
  ui.warn("Please specify server slices joined by dashes and not separate args:\n\n knife cluster #{sub_command} #{slice_string}\n\n")
78
83
  end
79
- slice_string.split(/[\s\-]/, 3)
84
+ slice_string.split(/[\s\-]/, 4)
80
85
  end
81
86
 
82
- def predicate_str(cluster_name, facet_name, slice_indexes)
83
- [ "#{ui.color(cluster_name, :bold)} cluster",
87
+ def predicate_str(realm_name, cluster_name, facet_name, slice_indexes)
88
+ [ "#{ui.color(realm_name, :bold)} realm",
89
+ (cluster_name ? "#{ui.color(cluster_name, :bold)} cluster" : "#{ui.color("all", :bold)} clusters"),
84
90
  (facet_name ? "#{ui.color(facet_name, :bold)} facet" : "#{ui.color("all", :bold)} facets"),
85
91
  (slice_indexes ? "servers #{ui.color(slice_indexes, :bold)}" : "#{ui.color("all", :bold)} servers")
86
92
  ].join(', ')
@@ -185,10 +191,44 @@ module Ironfan
185
191
  end
186
192
  end
187
193
 
194
+ def wait_for_ssh(computer)
195
+ ssh = Chef::Knife::Ssh.new
196
+ ssh.ui = ui
197
+ ssh.name_args = [ computer.name, "ls" ]
198
+ ssh.config[:ssh_user] = Chef::Config[:knife][:ssh_user] || config[:ssh_user]
199
+ ssh.config[:ssh_password] = config[:ssh_password]
200
+ ssh.config[:ssh_port] = Chef::Config[:knife][:ssh_port] || config[:ssh_port]
201
+ ssh.config[:ssh_gateway] = Chef::Config[:knife][:ssh_gateway] || config[:ssh_gateway]
202
+ ssh.config[:forward_agent] = Chef::Config[:knife][:forward_agent] || config[:forward_agent]
203
+ ssh.config[:identity_file] = Chef::Config[:knife][:identity_file] || config[:identity_file]
204
+ ssh.config[:manual] = true
205
+ ssh.config[:host_key_verify] = Chef::Config[:knife][:host_key_verify] || config[:host_key_verify]
206
+ ssh.config[:on_error] = :raise
207
+ session = ssh.session
208
+ return true
209
+ rescue Errno::ETIMEDOUT
210
+ Chef::Log.debug("ssh to #{computer.name} timed out")
211
+ return false
212
+ rescue Errno::ECONNREFUSED
213
+ Chef::Log.debug("ssh connection to #{computer.name} refused")
214
+ yield
215
+ return false
216
+ rescue Errno::EHOSTUNREACH
217
+ Chef::Log.debug("ssh host #{computer.name} unreachable")
218
+ yield
219
+ return false
220
+ rescue
221
+ Chef::Log.debug("something else went wrong while wating for ssh host #{computer.name}")
222
+ raise
223
+ return false
224
+ else
225
+ session && session.close
226
+ session = nil
227
+ end
228
+
188
229
  #
189
230
  # Utilities
190
231
  #
191
-
192
232
  def sub_command
193
233
  self.class.sub_command
194
234
  end
@@ -15,9 +15,6 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
  #
18
-
19
- require File.expand_path('ironfan_knife_common', File.dirname(File.realdirpath(__FILE__)))
20
-
21
18
  module Ironfan
22
19
  class Script < Chef::Knife
23
20
  include Ironfan::KnifeCommon
@@ -34,6 +34,7 @@ module Ironfan
34
34
  # Discovery
35
35
  #
36
36
  def correlate
37
+ Chef::Log.info chosen_resources
37
38
  chosen_resources.each do |res|
38
39
  res.expected_ids(self).each do |id|
39
40
  next unless res.recall? id
@@ -272,12 +273,12 @@ module Ironfan
272
273
  self.item_type = Computer
273
274
  self.key_method = :object_id
274
275
  delegate :first, :map, :any?, :to => :values
275
- attr_accessor :cluster
276
+ attr_accessor :clusters
276
277
 
277
278
  def initialize(*args)
278
279
  super
279
280
  options = args.pop or return
280
- self.cluster = options[:cluster]
281
+ self.clusters = options[:clusters]
281
282
  create_expected!
282
283
  end
283
284
 
@@ -338,9 +339,10 @@ module Ironfan
338
339
 
339
340
  # set up new computers for each server in the cluster definition
340
341
  def create_expected!
341
- self.cluster.servers.each do |server|
342
+ servers = self.clusters.map{ |c| c.servers.to_a }.flatten
343
+ servers.each do |server|
342
344
  self << Computer.new(:server => server)
343
- end unless self.cluster.nil?
345
+ end unless self.clusters.nil?
344
346
  end
345
347
 
346
348
  # Return the selection inside another Computers collection
@@ -352,23 +354,24 @@ module Ironfan
352
354
 
353
355
  def empty_copy
354
356
  result = self.class.new
355
- result.cluster = self.cluster unless self.cluster.nil?
357
+ result.clusters = self.clusters unless self.clusters.nil?
356
358
  result
357
359
  end
358
360
 
359
361
  # Find all selected computers, as well as any bogus computers from discovery
360
- def slice(facet_name=nil, slice_indexes=nil)
361
- return self if (facet_name.nil? && slice_indexes.nil?)
362
- slice_array = build_slice_array(slice_indexes)
362
+ def slice(cluster_name = nil, facet_name = nil, slice_indexes = nil)
363
+ return self if cluster_name.nil? && facet_name.nil? && slice_indexes.nil?
364
+ slice_array = build_slice_array(slice_indexes)
363
365
  select do |mach|
364
- mach.bogus? or (
366
+ mach.bogus? || (
365
367
  # facet match, and index match (or no indexes specified)
366
- (mach.server.facet_name == facet_name) &&
368
+ (mach.server.cluster_name == cluster_name) &&
369
+ (mach.server.facet_name == facet_name || facet_name.nil?) &&
367
370
  (slice_array.include?(mach.server.index) || slice_indexes.nil?))
368
371
  end
369
372
  end
370
373
 
371
- def build_slice_array(slice_indexes)
374
+ def build_slice_array slice_indexes
372
375
  return [] if slice_indexes.nil?
373
376
  raise "Bad slice_indexes: #{slice_indexes}" if slice_indexes =~ /[^0-9\.,]/
374
377
  eval("[#{slice_indexes}]").map {|idx| idx.class == Range ? idx.to_a : idx}.flatten
@@ -11,22 +11,27 @@ module Ironfan
11
11
  # Take in a Dsl::Cluster; return Computers populated with all discovered
12
12
  # resources that correlate; computers corresponding to partial or
13
13
  # unrecognizable resources are labeled as bogus.
14
- def discover!(cluster)
14
+ def discover!(clusters, with_cloud = true)
15
15
 
16
16
  # Get fully resolved servers, and build Computers using them
17
- computers = Computers.new(:cluster => cluster)
18
- #
19
- providers = computers.map{|c| c.providers.values }.flatten.uniq
20
- Ironfan.parallel(providers) do |provider|
21
- Ironfan.step cluster.name, "Loading #{provider.handle}", :cyan
22
- provider.load cluster
17
+ computers = Computers.new(clusters: Array(clusters))
18
+ #
19
+ if with_cloud
20
+ providers = computers.map{|c| c.providers.values }.flatten.uniq
21
+ Ironfan.parallel(providers) do |provider|
22
+ clusters.each do |cluster|
23
+ Ironfan.step cluster.name, "Loading #{provider.handle}", :cyan
24
+ provider.load cluster
25
+ end
26
+ end
27
+ #
28
+ clusters.each do |cluster|
29
+ Ironfan.step cluster.name, "Reconciling DSL and provider information", :cyan
30
+ end
31
+ computers.correlate
32
+ computers.validate
23
33
  end
24
34
  #
25
- Ironfan.step cluster.name, "Reconciling DSL and provider information", :cyan
26
-
27
- computers.correlate
28
- computers.validate
29
- #
30
35
  computers
31
36
  end
32
37
 
@@ -0,0 +1,155 @@
1
+ module Ironfan
2
+
3
+ module CookbookRequirements
4
+ extend Gorillib::Concern
5
+
6
+ def join_req(req1, req2)
7
+ # order requirements by operation: =, >=, ~>
8
+ req1, req2 = (req1.constraint < req2.constraint) ? [req1, req2] : [req2, req1]
9
+ cn1, cn2 = [req1.constraint, req2.constraint]
10
+ vers1, vers2 = [cn1.split.last, cn2.split.last]
11
+ vers1_c, vers2_c = [vers1.split('.'), vers2.split('.')]
12
+ op1, op2 = [req1, req2].map{ |x| x.constraint.split.first }
13
+
14
+ if op1 == '=' && op2 == '='
15
+ join_eq_eq(req1, req2)
16
+ elsif op1 == '>=' && op2 == '>='
17
+ join_geq_geq(req1, req2)
18
+ elsif op1 == '~>' && op2 == '~>'
19
+ join_agt_agt(req1, req2)
20
+ elsif op1 == '=' && op2 == '>='
21
+ join_eq_gte(req1, req2)
22
+ elsif op1 == '=' && op2 == '~>'
23
+ join_eq_agt(req1, req2)
24
+ elsif op1 == '>=' && op2 == '~>'
25
+ join_gte_agt(req1, req2)
26
+ end
27
+ end
28
+
29
+ def cookbook_req(name, constraint)
30
+ (@cookbook_reqs ||= []) << self.class.new_req(name, constraint)
31
+ end
32
+
33
+ def children
34
+ []
35
+ end
36
+
37
+ def cookbook_reqs
38
+ Hash[_cookbook_reqs.map{ |x| [x.name, x.constraint] }]
39
+ end
40
+
41
+ def _cookbook_reqs
42
+ [
43
+ *shallow_cookbook_reqs,
44
+ *child_cookbook_reqs
45
+ ].group_by(&:name).values.map do |group|
46
+ group.inject{ |result, req| join_req(result, req) }
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ #-----------------------------------------------------------------------------------------------
53
+
54
+ def join_eq_eq(req1, req2)
55
+ (vers(req1) == vers(req2)) ? req1 : bad_reqs(req1, req2)
56
+ end
57
+
58
+ def join_geq_geq(req1, req2)
59
+ (vers(req1) >= vers(req2)) ? req1 : req2
60
+ end
61
+
62
+ def join_agt_agt(req1, req2)
63
+ if vers_a(req1).size == vers_a(req2).size &&
64
+ vers_a_head(req1).zip(vers_a_head(req2)).all?{|v1,v2| v1 == v2}
65
+ (req1.constraint > req2.constraint) ? req1 : req2
66
+ else
67
+ bad_reqs(req1, req2)
68
+ end
69
+ end
70
+
71
+ def join_eq_gte(req1, req2)
72
+ vers(req1) >= vers(req2) ? req1 : bad_reqs(req1, req2)
73
+ end
74
+
75
+ def join_eq_agt(req1, req2)
76
+ if match_v_head(req1, req2) &&
77
+ vers_a(req1)[vers_a(req2).size - 1] >= vers_a(req2).last
78
+ req1
79
+ else
80
+ bad_reqs(req1, req2)
81
+ end
82
+ end
83
+
84
+ def join_gte_agt(req1, req2)
85
+ if match_v_head(req1, req2) && vers(req1) <= vers(req2)
86
+ req2
87
+ else
88
+ bad_reqs(req1, req2)
89
+ end
90
+ end
91
+
92
+ def match_v_head(req1, req2)
93
+ vers_a_head(req1, vers_a(req2).size).zip(vers_a_head(req2)).all?{|v1,v2| v1 == v2}
94
+ end
95
+
96
+ def op req
97
+ req.constraint.split.first
98
+ end
99
+
100
+ def vers req
101
+ req.constraint.split.last
102
+ end
103
+
104
+ def vers_a req
105
+ vers(req).split('.')
106
+ end
107
+
108
+ def vers_a_head(req, last = 0)
109
+ vers_a(req)[0...last - 1]
110
+ end
111
+
112
+ #-----------------------------------------------------------------------------------------------
113
+
114
+ def bad_reqs(req1, req2)
115
+ raise ArgumentError.new("#{req1.name}: cannot reconcile #{req1.constraint} with #{req2.constraint}")
116
+ end
117
+
118
+ def child_cookbook_reqs
119
+ children.map(&:_cookbook_reqs).flatten(1)
120
+ end
121
+
122
+ def shallow_cookbook_reqs
123
+ @cookbook_reqs || self.class.default_cookbook_reqs
124
+ end
125
+
126
+ module ClassMethods
127
+
128
+ def require_strict_versioning?
129
+ @require_strict = true if @require_strict.nil?
130
+ @require_strict
131
+ end
132
+
133
+ def require_strict_versioning choice
134
+ @require_strict = choice
135
+ end
136
+
137
+ def new_req(name, constraint)
138
+ if constraint.start_with?('>=') && require_strict_versioning?
139
+ raise StandardError.new("Please don't use >= constraints. They're too vague!")
140
+ else
141
+ Ironfan::Plugin::CookbookRequirement.new(name: name, constraint: constraint)
142
+ end
143
+ end
144
+
145
+ def default_cookbook_reqs
146
+ @default_cookbook_reqs ||= []
147
+ end
148
+
149
+ def cookbook_req(name, constraint)
150
+ default_cookbook_reqs << new_req(name, constraint)
151
+ end
152
+
153
+ end
154
+ end
155
+ end
@@ -14,6 +14,8 @@ module Ironfan
14
14
  when :virtualbox then VirtualBox
15
15
  when :vsphere then Vsphere
16
16
  when :rds then Rds
17
+ when :openstack then OpenStack
18
+ when :static then Static
17
19
  else raise "Unsupported cloud #{obj[:name]}"
18
20
  end
19
21
  end
@@ -1,35 +1,45 @@
1
1
  module Ironfan
2
2
  class Dsl
3
-
4
3
  class Cluster < Ironfan::Dsl::Compute
5
- collection :facets, Ironfan::Dsl::Facet, :resolver => :deep_resolve
6
4
  include Ironfan::Plugin::Base; register_with Ironfan::Dsl::Realm
7
5
 
8
- def children
9
- facets.to_a + components.to_a
6
+ collection :facets, Ironfan::Dsl::Facet, resolver: :deep_resolve
7
+
8
+ def self.plugin_hook(owner, attrs, plugin_name, full_name, &blk)
9
+ owner.cluster(plugin_name, new(attrs.merge(name: full_name, owner: owner)))
10
+ _project(cluster, &blk)
11
+ end
12
+
13
+ def self.definitions
14
+ @clusters ||= {}
10
15
  end
11
16
 
12
- def initialize(attrs={},&block)
17
+ def self.define(attrs = {}, &blk)
18
+ cl = new(attrs)
19
+ cl.receive!({}, &blk) # the ordering of the initialize method is super fragile
20
+ definitions[attrs[:name].to_sym] = cl
21
+ end
22
+
23
+ def initialize(attrs = {}, &blk)
13
24
  super
14
- self.cluster_role Ironfan::Dsl::Role.new(:name => "#{attrs[:name]}-cluster")
15
- self.realm_name attrs[:owner].name unless attrs[:owner].nil?
16
- self.cluster_names attrs[:owner].cluster_names unless attrs[:owner].nil?
25
+ self.cluster_role Ironfan::Dsl::Role.new(name: "#{attrs[:name]}-cluster")
26
+ self.realm_name attrs[:owner].name unless attrs[:owner].nil?
27
+ self.cluster_names attrs[:owner].cluster_names unless attrs[:owner].nil?
17
28
  end
18
29
 
19
30
  # Utility method to reference all servers from constituent facets
20
31
  def servers
21
- result = Gorillib::ModelCollection.new(:item_type => Ironfan::Dsl::Server, :key_method => :full_name)
22
- facets.each {|f| f.servers.each {|s| result << s} }
32
+ result = Gorillib::ModelCollection.new(item_type: Ironfan::Dsl::Server, key_method: :full_name)
33
+ facets.each{ |f| f.servers.each{ |s| result << s } }
23
34
  result
24
35
  end
25
36
 
26
- def cluster_name
27
- name
37
+ def children
38
+ facets.to_a + components.to_a
28
39
  end
29
40
 
30
- def self.plugin_hook owner, attrs, plugin_name, full_name, &blk
31
- owner.cluster(plugin_name, new(attrs.merge(name: full_name, owner: owner)))
32
- _project cluster, &blk
41
+ def cluster_name
42
+ name
33
43
  end
34
44
  end
35
45
  end
@@ -6,14 +6,14 @@ module Ironfan
6
6
  include Ironfan::Plugin::Base; register_with Ironfan::Dsl::Compute
7
7
 
8
8
  field :cluster_name, Symbol
9
- field :facet_name, Symbol
10
- field :realm_name, Symbol
11
- field :name, Symbol
9
+ field :facet_name, Symbol
10
+ field :realm_name, Symbol
11
+ field :name, Symbol
12
12
 
13
13
  def initialize(attrs, &blk)
14
- attrs.merge!(facet_name: (attrs[:owner].name unless attrs[:owner].nil? or not attrs[:owner].is_a?(Facet)),
14
+ attrs.merge!(facet_name: (attrs[:owner].name unless attrs[:owner].nil? or not attrs[:owner].is_a?(Facet)),
15
15
  cluster_name: (attrs[:owner].cluster_name unless attrs[:owner].nil?),
16
- realm_name: (attrs[:owner].realm_name unless attrs[:owner].nil?))
16
+ realm_name: (attrs[:owner].realm_name unless attrs[:owner].nil?))
17
17
  super attrs, &blk
18
18
  end
19
19
 
@@ -34,8 +34,8 @@ module Ironfan
34
34
 
35
35
  def self.from_node(node = NilCheckDelegate.new(nil))
36
36
  cluster_name = node['cluster_name'].to_s
37
- super(node).tap{|x| x.receive!(cluster_name: cluster_name,
38
- realm_name: cluster_name.split('_').first)}
37
+ realm_name = node['realm_name'].to_s
38
+ super(node).tap{ |x| x.receive!(cluster_name: cluster_name, realm_name: realm_name) }
39
39
  end
40
40
 
41
41
  def self.announce_name
@@ -94,7 +94,7 @@ module Ironfan
94
94
  end
95
95
  end
96
96
 
97
- def set_discovery compute, keys
97
+ def set_discovery(compute, keys)
98
98
  if server_cluster
99
99
  wire_to(compute, full_server_cluster, keys)
100
100
  else
@@ -110,14 +110,11 @@ module Ironfan
110
110
  discovery = {discovers: keys.reverse.inject(full_server_cluster_v){|hsh,key| {key => hsh}}}
111
111
  (compute.facet_role || compute.cluster_role).override_attributes(discovery)
112
112
 
113
- # FIXME: This is Ec2-specific and probably doesn't belong here.
114
113
  client_group_v = client_group(compute)
115
114
  server_group_v = security_group(full_server_cluster_v)
116
115
 
117
- if create_security_groups
118
- group_edge(compute.cloud(:ec2), client_group_v, :authorized_by_group, server_group_v)
119
- group_edge(compute.cloud(:ec2), client_group_v, :authorize_group, server_group_v) if bidirectional
120
- end
116
+ group_edge(compute, client_group_v, :authorized_by_group, server_group_v)
117
+ group_edge(compute, client_group_v, :authorize_group, server_group_v) if bidirectional
121
118
 
122
119
  Chef::Log.debug("discovered #{announce_name} for #{cluster_name}: #{discovery}")
123
120
  end
@@ -125,11 +122,11 @@ module Ironfan
125
122
  protected
126
123
 
127
124
  def client_group(compute)
128
- security_group(compute.cluster_name)
125
+ security_group(compute.cluster_name, (compute.name if compute.is_a?(Facet)))
129
126
  end
130
127
 
131
128
  def full_server_cluster
132
- "#{realm_name}_#{server_cluster}"
129
+ server_cluster
133
130
  end
134
131
 
135
132
  def group_edge(cloud, group_1, method, group_2)
@@ -15,24 +15,26 @@ module Ironfan
15
15
 
16
16
  class Compute < Ironfan::Dsl
17
17
  @@run_list_rank = 0
18
- field :name, String
18
+ field :name, String
19
19
 
20
20
  # Resolve each of the following as a merge of their container's attributes and theirs
21
- collection :components, Ironfan::Dsl::Component, :resolver => :merge_resolve, :key_method => :name
21
+ collection :components, Ironfan::Dsl::Component, :resolver => :merge_resolve, :key_method => :name
22
22
  collection :run_list_items, RunListItem, :resolver => :merge_resolve, :key_method => :name
23
23
  collection :clouds, Ironfan::Dsl::Cloud, :resolver => :merge_resolve, :key_method => :name
24
24
  collection :volumes, Ironfan::Dsl::Volume, :resolver => :merge_resolve, :key_method => :name
25
+ collection :security_groups, Ironfan::Dsl::SecurityGroup, :resolver => :merge_resolve, :key_method => :name
25
26
 
26
27
  # Resolve these normally (overriding on each layer)
27
- magic :environment, Symbol, :default => :_default
28
- magic :use_cloud, Symbol
28
+ magic :environment, Symbol, default: :_default
29
+ magic :realm_name, Symbol, default: :_default
30
+ magic :use_cloud, Symbol
29
31
 
30
- member :cluster_role, Ironfan::Dsl::Role
31
- member :facet_role, Ironfan::Dsl::Role
32
+ member :cluster_role, Ironfan::Dsl::Role
33
+ member :facet_role, Ironfan::Dsl::Role
32
34
 
33
- magic :cluster_names, Whatever
34
- magic :realm_name, Symbol
35
+ magic :cluster_names, Whatever
35
36
 
37
+ magic :dns_domain, String
36
38
  field :source_file, String
37
39
 
38
40
  extend Gorillib::Concern
@@ -30,12 +30,13 @@ module Ironfan
30
30
  magic :auto_elastic_ip, String
31
31
  magic :allocation_id, String
32
32
  magic :region, String, :default => ->{ default_region }
33
- collection :security_groups, Ironfan::Dsl::Ec2::SecurityGroup, :key_method => :name
33
+ collection :security_groups, Ironfan::Dsl::SecurityGroup, :key_method => :name
34
34
  magic :ssh_user, String, :default => ->{ image_info[:ssh_user] }
35
35
  magic :ssh_identity_dir, String, :default => ->{ Chef::Config.ec2_key_dir }
36
36
  magic :subnet, String
37
37
  magic :validation_key, String, :default => ->{ IO.read(Chef::Config.validation_key) rescue '' }
38
38
  magic :vpc, String
39
+ magic :dns_search_domain, String, :default => 'internal'
39
40
 
40
41
  def domain; vpc.nil? ? 'standard' : 'vpc'; end
41
42
 
@@ -125,31 +126,6 @@ module Ironfan
125
126
  end
126
127
  end
127
128
 
128
- class SecurityGroup < Ironfan::Dsl
129
- field :name, String
130
- field :group_authorized, Array, :default => []
131
- field :group_authorized_by, Array, :default => []
132
- field :range_authorizations, Array, :default => []
133
-
134
- def authorize_port_range(range, cidr_ip = '0.0.0.0/0', ip_protocol = 'tcp')
135
- range = (range .. range) if range.is_a?(Integer)
136
- range_authorizations << [range, cidr_ip, ip_protocol]
137
- range_authorizations.compact!
138
- range_authorizations.uniq!
139
- end
140
-
141
- def authorized_by_group(other_name)
142
- group_authorized_by << other_name.to_s
143
- group_authorized_by.compact!
144
- group_authorized_by.uniq!
145
- end
146
-
147
- def authorize_group(other_name)
148
- group_authorized << other_name.to_s
149
- group_authorized.compact!
150
- group_authorized.uniq!
151
- end
152
- end
153
129
 
154
130
  class ElasticLoadBalancer
155
131
 
@@ -4,29 +4,31 @@ module Ironfan
4
4
  class Facet < Ironfan::Dsl::Compute
5
5
  include Ironfan::Plugin::Base; register_with Ironfan::Dsl::Cluster
6
6
 
7
- magic :instances, Integer, :default => 1
8
- collection :servers, Ironfan::Dsl::Server, :resolver => :deep_resolve
7
+ magic :instances, Integer, default: 1
8
+ collection :servers, Ironfan::Dsl::Server, resolver: :deep_resolve
9
9
  field :cluster_name, String
10
10
 
11
- def initialize(attrs={},&block)
12
- self.cluster_names attrs[:owner].cluster_names unless attrs[:owner].nil?
13
- self.realm_name attrs[:owner].realm_name unless attrs[:owner].nil?
14
- self.cluster_name = attrs[:owner].cluster_name unless attrs[:owner].nil?
15
- self.name = attrs[:name] unless attrs[:name].nil?
16
- self.facet_role Ironfan::Dsl::Role.new(:name => "#{full_name}-facet")
11
+ def self.plugin_hook(owner, attrs, plugin_name, full_name, &blk)
12
+ facet = owner.facet(plugin_name, new(attrs.merge(name: plugin_name, owner: owner)))
13
+ _project(facet, &blk)
14
+ end
15
+
16
+ def initialize(attrs = {}, &blk)
17
+ self.cluster_names attrs[:owner].cluster_names unless attrs[:owner].nil?
18
+ self.realm_name attrs[:owner].realm_name unless attrs[:owner].nil?
19
+ self.cluster_name = attrs[:owner].cluster_name unless attrs[:owner].nil?
20
+ self.name = attrs[:name] unless attrs[:name].nil?
21
+ self.facet_role Ironfan::Dsl::Role.new(name: "#{full_name}-facet")
17
22
  super
18
- for i in 0 .. instances-1; server(i); end
23
+ (0..instances - 1).each{ |idx| server idx }
19
24
  end
20
25
 
21
26
  def children
22
27
  servers.to_a + components.to_a
23
28
  end
24
29
 
25
- def full_name() "#{cluster_name}-#{name}"; end
26
-
27
- def self.plugin_hook owner, attrs, plugin_name, full_name, &blk
28
- facet = owner.facet(plugin_name, new(attrs.merge(name: plugin_name, owner: owner)))
29
- _project facet, &blk
30
+ def full_name
31
+ "#{cluster_name}-#{name}"
30
32
  end
31
33
  end
32
34
  end