ironfan 5.0.11 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.gitmodules +3 -0
- data/Gemfile +8 -26
- data/Gemfile.lock +38 -41
- data/NOTES-REALM.md +172 -0
- data/Rakefile +19 -77
- data/config/ubuntu12.04-ironfan.erb +7 -0
- data/ironfan.gemspec +28 -225
- data/lib/chef/cluster_knife.rb +26 -0
- data/lib/chef/knife/bootstrap/ubuntu12.04-ironfan.erb +7 -0
- data/lib/chef/knife/cluster_bootstrap.rb +1 -3
- data/lib/chef/knife/cluster_diff.rb +2 -8
- data/lib/chef/knife/cluster_kick.rb +1 -3
- data/lib/chef/knife/cluster_kill.rb +1 -2
- data/lib/chef/knife/cluster_launch.rb +17 -34
- data/lib/chef/knife/cluster_list.rb +6 -5
- data/lib/chef/knife/cluster_proxy.rb +1 -3
- data/lib/chef/knife/cluster_pry.rb +1 -2
- data/lib/chef/knife/cluster_show.rb +6 -7
- data/lib/chef/knife/cluster_ssh.rb +10 -8
- data/lib/chef/knife/cluster_start.rb +1 -2
- data/lib/chef/knife/cluster_stop.rb +1 -2
- data/lib/chef/knife/cluster_sync.rb +2 -3
- data/lib/chef/knife/ironfan_knife_common.rb +58 -18
- data/lib/chef/knife/ironfan_script.rb +0 -3
- data/lib/ironfan/broker/computer.rb +14 -11
- data/lib/ironfan/broker.rb +17 -12
- data/lib/ironfan/cookbook_requirements.rb +155 -0
- data/lib/ironfan/dsl/cloud.rb +2 -0
- data/lib/ironfan/dsl/cluster.rb +25 -15
- data/lib/ironfan/dsl/component.rb +12 -15
- data/lib/ironfan/dsl/compute.rb +10 -8
- data/lib/ironfan/dsl/ec2.rb +2 -26
- data/lib/ironfan/dsl/facet.rb +16 -14
- data/lib/ironfan/dsl/openstack.rb +147 -0
- data/lib/ironfan/dsl/realm.rb +23 -16
- data/lib/ironfan/dsl/security_group.rb +29 -0
- data/lib/ironfan/dsl/server.rb +14 -5
- data/lib/ironfan/dsl/static.rb +63 -0
- data/lib/ironfan/dsl/vsphere.rb +1 -0
- data/lib/ironfan/dsl.rb +1 -134
- data/lib/ironfan/headers.rb +19 -0
- data/lib/ironfan/provider/chef/node.rb +3 -2
- data/lib/ironfan/provider/ec2/machine.rb +10 -14
- data/lib/ironfan/provider/ec2/security_group.rb +58 -43
- data/lib/ironfan/provider/openstack/elastic_ip.rb +96 -0
- data/lib/ironfan/provider/openstack/keypair.rb +78 -0
- data/lib/ironfan/provider/openstack/machine.rb +371 -0
- data/lib/ironfan/provider/openstack/security_group.rb +224 -0
- data/lib/ironfan/provider/openstack.rb +69 -0
- data/lib/ironfan/provider/static/machine.rb +192 -0
- data/lib/ironfan/provider/static.rb +23 -0
- data/lib/ironfan/provider.rb +58 -1
- data/lib/ironfan/requirements.rb +17 -1
- data/lib/ironfan/version.rb +3 -0
- data/lib/ironfan.rb +107 -172
- data/spec/chef/cluster_bootstrap_spec.rb +2 -7
- data/spec/chef/cluster_launch_spec.rb +1 -2
- data/spec/fixtures/realms/samurai.rb +26 -0
- data/spec/integration/minimal-chef-repo/clusters/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/config/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/.gitignore +1 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/certificates/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/client_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/data_bag_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ec2_certs/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ec2_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ironfantest-validator.pem +27 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ironfantester.pem +27 -0
- data/spec/integration/minimal-chef-repo/tasks/.gitkeep +0 -0
- data/spec/ironfan/cluster_spec.rb +1 -2
- data/spec/ironfan/diff_spec.rb +0 -2
- data/spec/ironfan/dsl_spec.rb +6 -3
- data/spec/ironfan/ec2/cloud_provider_spec.rb +17 -18
- data/spec/ironfan/ec2/elb_spec.rb +44 -41
- data/spec/ironfan/ec2/security_group_spec.rb +45 -47
- data/spec/ironfan/manifest_spec.rb +0 -1
- data/spec/ironfan/plugin_spec.rb +55 -40
- data/spec/ironfan/realm_spec.rb +42 -30
- data/spec/spec_helper.rb +17 -31
- data/spec/{spec_helper → support}/dummy_chef.rb +0 -0
- data/spec/{spec_helper → support}/dummy_diff_drawer.rb +0 -0
- metadata +78 -155
- data/.rspec +0 -2
- data/.yardopts +0 -19
- data/VERSION +0 -2
- data/chefignore +0 -41
- data/notes/Future-development-proposals.md +0 -266
- data/notes/Home.md +0 -55
- data/notes/INSTALL-cloud_setup.md +0 -103
- data/notes/INSTALL.md +0 -134
- data/notes/Ironfan-Roadmap.md +0 -70
- data/notes/Upgrading-to-v4.md +0 -66
- data/notes/advanced-superpowers.md +0 -16
- data/notes/aws_servers.jpg +0 -0
- data/notes/aws_user_key.png +0 -0
- data/notes/cookbook-versioning.md +0 -11
- data/notes/core_concepts.md +0 -200
- data/notes/declaring_volumes.md +0 -3
- data/notes/design_notes-aspect_oriented_devops.md +0 -36
- data/notes/design_notes-ci_testing.md +0 -169
- data/notes/design_notes-cookbook_event_ordering.md +0 -249
- data/notes/design_notes-meta_discovery.md +0 -59
- data/notes/ec2-pricing_and_capacity.md +0 -75
- data/notes/ec2-pricing_and_capacity.numbers +0 -0
- data/notes/homebase-layout.txt +0 -102
- data/notes/knife-cluster-commands.md +0 -21
- data/notes/named-cloud-objects.md +0 -11
- data/notes/opscode_org_key.png +0 -0
- data/notes/opscode_user_key.png +0 -0
- data/notes/philosophy.md +0 -13
- data/notes/rake_tasks.md +0 -24
- data/notes/renamed-recipes.txt +0 -142
- data/notes/silverware.md +0 -85
- data/notes/style_guide.md +0 -300
- data/notes/tips_and_troubleshooting.md +0 -92
- data/notes/walkthrough-hadoop.md +0 -168
- data/notes/walkthrough-web.md +0 -166
- data/spec/fixtures/gunbai.rb +0 -24
- data/spec/test_config.rb +0 -20
- 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
|
20
|
-
self.config[:cloud]
|
21
|
-
Ironfan.
|
22
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
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\-]/,
|
84
|
+
slice_string.split(/[\s\-]/, 4)
|
80
85
|
end
|
81
86
|
|
82
|
-
def predicate_str(cluster_name, facet_name, slice_indexes)
|
83
|
-
[ "#{ui.color(
|
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 :
|
276
|
+
attr_accessor :clusters
|
276
277
|
|
277
278
|
def initialize(*args)
|
278
279
|
super
|
279
280
|
options = args.pop or return
|
280
|
-
self.
|
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.
|
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.
|
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.
|
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
|
362
|
-
slice_array
|
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?
|
366
|
+
mach.bogus? || (
|
365
367
|
# facet match, and index match (or no indexes specified)
|
366
|
-
(mach.server.
|
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
|
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
|
data/lib/ironfan/broker.rb
CHANGED
@@ -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!(
|
14
|
+
def discover!(clusters, with_cloud = true)
|
15
15
|
|
16
16
|
# Get fully resolved servers, and build Computers using them
|
17
|
-
computers = Computers.new(:
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
Ironfan.
|
22
|
-
|
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
|
data/lib/ironfan/dsl/cloud.rb
CHANGED
data/lib/ironfan/dsl/cluster.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
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
|
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
|
15
|
-
self.realm_name
|
16
|
-
self.cluster_names
|
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(:
|
22
|
-
facets.each
|
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
|
27
|
-
|
37
|
+
def children
|
38
|
+
facets.to_a + components.to_a
|
28
39
|
end
|
29
40
|
|
30
|
-
def
|
31
|
-
|
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,
|
10
|
-
field :realm_name,
|
11
|
-
field :name,
|
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:
|
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:
|
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
|
-
|
38
|
-
|
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
|
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
|
-
|
118
|
-
|
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
|
-
|
129
|
+
server_cluster
|
133
130
|
end
|
134
131
|
|
135
132
|
def group_edge(cloud, group_1, method, group_2)
|
data/lib/ironfan/dsl/compute.rb
CHANGED
@@ -15,24 +15,26 @@ module Ironfan
|
|
15
15
|
|
16
16
|
class Compute < Ironfan::Dsl
|
17
17
|
@@run_list_rank = 0
|
18
|
-
field :name,
|
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,
|
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,
|
28
|
-
magic :
|
28
|
+
magic :environment, Symbol, default: :_default
|
29
|
+
magic :realm_name, Symbol, default: :_default
|
30
|
+
magic :use_cloud, Symbol
|
29
31
|
|
30
|
-
member :cluster_role,
|
31
|
-
member :facet_role,
|
32
|
+
member :cluster_role, Ironfan::Dsl::Role
|
33
|
+
member :facet_role, Ironfan::Dsl::Role
|
32
34
|
|
33
|
-
magic :cluster_names,
|
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
|
data/lib/ironfan/dsl/ec2.rb
CHANGED
@@ -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::
|
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
|
|
data/lib/ironfan/dsl/facet.rb
CHANGED
@@ -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,
|
8
|
-
collection :servers, Ironfan::Dsl::Server,
|
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
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
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
|