ironfan 4.2.1 → 4.2.2
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/CHANGELOG.md +10 -1
- data/VERSION +1 -1
- data/ironfan.gemspec +7 -3
- data/lib/chef/knife/cluster_bootstrap.rb +13 -0
- data/lib/chef/knife/cluster_pry.rb +6 -3
- data/lib/chef/knife/cluster_show.rb +1 -0
- data/lib/gorillib/resolution.rb +9 -9
- data/lib/ironfan/broker/computer.rb +31 -8
- data/lib/ironfan/broker.rb +5 -4
- data/lib/ironfan/dsl/cloud.rb +12 -8
- data/lib/ironfan/dsl/compute.rb +14 -4
- data/lib/ironfan/dsl/ec2.rb +11 -3
- data/lib/ironfan/dsl/virtualbox.rb +2 -2
- data/lib/ironfan/headers.rb +1 -1
- data/lib/ironfan/provider/ec2/ebs_volume.rb +6 -0
- data/lib/ironfan/provider/ec2/elastic_ip.rb +1 -2
- data/lib/ironfan/provider/ec2/{key_pair.rb → keypair.rb} +15 -7
- data/lib/ironfan/provider/ec2/machine.rb +13 -7
- data/lib/ironfan/provider/ec2/security_group.rb +12 -2
- data/lib/ironfan/provider/ec2.rb +1 -1
- data/lib/ironfan/provider.rb +16 -7
- data/lib/ironfan/requirements.rb +1 -3
- data/lib/ironfan.rb +14 -10
- data/spec/chef/cluster_bootstrap_spec.rb +51 -0
- data/spec/fixtures/gunbai.rb +24 -0
- data/spec/fixtures/gunbai_slice.json +330 -0
- data/spec/ironfan/ec2/cloud_provider.rb +35 -0
- data/spec/spec_helper.rb +26 -1
- metadata +11 -3
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
+
# v4.2.2: @mrflip rocks the house
|
2
|
+
* Terminated machines are not bogus (fixes #165)
|
3
|
+
* Ignore deleting, deleted, or errored volumes in discovery
|
4
|
+
* Rescue on duplicate security groups; don't die logging on full 'load!'
|
5
|
+
* Changed key_pair to keypair, as per the DSL
|
6
|
+
* Specs for scripts (but not really)
|
7
|
+
* Model cleanup -- now mostly round-trip to JSON
|
8
|
+
* knife cluster bootstrap sets Chef::Config[:environment] (fixes #148)
|
9
|
+
|
1
10
|
# v4.2.1: @nickmarden rocks the house
|
2
|
-
*
|
11
|
+
* Correct merging of cluster and facet objects, with specs (fixes #158)
|
3
12
|
* Circumvent memory bloat by resolving just once
|
4
13
|
|
5
14
|
# v4.2.0:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.2.
|
1
|
+
4.2.2
|
data/ironfan.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ironfan"
|
8
|
-
s.version = "4.2.
|
8
|
+
s.version = "4.2.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Infochimps"]
|
@@ -77,14 +77,18 @@ Gem::Specification.new do |s|
|
|
77
77
|
"lib/ironfan/provider/ec2.rb",
|
78
78
|
"lib/ironfan/provider/ec2/ebs_volume.rb",
|
79
79
|
"lib/ironfan/provider/ec2/elastic_ip.rb",
|
80
|
-
"lib/ironfan/provider/ec2/
|
80
|
+
"lib/ironfan/provider/ec2/keypair.rb",
|
81
81
|
"lib/ironfan/provider/ec2/machine.rb",
|
82
82
|
"lib/ironfan/provider/ec2/placement_group.rb",
|
83
83
|
"lib/ironfan/provider/ec2/security_group.rb",
|
84
84
|
"lib/ironfan/provider/virtualbox.rb",
|
85
85
|
"lib/ironfan/provider/virtualbox/machine.rb",
|
86
86
|
"lib/ironfan/requirements.rb",
|
87
|
+
"spec/chef/cluster_bootstrap_spec.rb",
|
88
|
+
"spec/fixtures/gunbai.rb",
|
89
|
+
"spec/fixtures/gunbai_slice.json",
|
87
90
|
"spec/ironfan/cluster_spec.rb",
|
91
|
+
"spec/ironfan/ec2/cloud_provider.rb",
|
88
92
|
"spec/ironfan/ec2/cloud_provider_spec.rb",
|
89
93
|
"spec/ironfan/ec2/security_group_spec.rb",
|
90
94
|
"spec/spec_helper.rb",
|
@@ -97,7 +101,7 @@ Gem::Specification.new do |s|
|
|
97
101
|
s.require_paths = ["lib"]
|
98
102
|
s.rubygems_version = "1.8.24"
|
99
103
|
s.summary = "Ironfan allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks."
|
100
|
-
s.test_files = ["spec/spec_helper/dummy_chef.rb", "spec/ironfan/cluster_spec.rb", "spec/ironfan/ec2/cloud_provider_spec.rb", "spec/ironfan/ec2/security_group_spec.rb", "spec/spec_helper.rb", "spec/test_config.rb"]
|
104
|
+
s.test_files = ["spec/spec_helper/dummy_chef.rb", "spec/ironfan/cluster_spec.rb", "spec/ironfan/ec2/cloud_provider_spec.rb", "spec/ironfan/ec2/security_group_spec.rb", "spec/ironfan/ec2/cloud_provider.rb", "spec/chef/cluster_bootstrap_spec.rb", "spec/fixtures/gunbai_slice.json", "spec/fixtures/gunbai.rb", "spec/spec_helper.rb", "spec/test_config.rb"]
|
101
105
|
|
102
106
|
if s.respond_to? :specification_version then
|
103
107
|
s.specification_version = 3
|
@@ -59,6 +59,7 @@ class Chef
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def perform_execution(target)
|
62
|
+
reconcile_chef_config(target)
|
62
63
|
# Execute across all servers in parallel
|
63
64
|
Ironfan.parallel(target.values) {|computer| run_bootstrap(computer)}
|
64
65
|
# threads = target.servers.map{ |server| Thread.new(server) { |svr| run_bootstrap(svr, svr.public_hostname) } }
|
@@ -69,6 +70,18 @@ class Chef
|
|
69
70
|
confirm_or_exit("Are you absolutely certain that you want to perform this action? (Type 'Yes' to confirm) ", 'Yes')
|
70
71
|
end
|
71
72
|
|
73
|
+
protected
|
74
|
+
|
75
|
+
def reconcile_chef_config(target)
|
76
|
+
environments = target.environments
|
77
|
+
if environments.length > 1
|
78
|
+
ui.error "You cannot bootstrap machines in multiple chef environments: got #{environments.inspect} from #{target.map(&:name)}"
|
79
|
+
ui.error "Re-run this command on each subgroup of machines that share an environment"
|
80
|
+
raise StandardError, "Cannot bootstrap multiple chef environments"
|
81
|
+
end
|
82
|
+
Chef::Config[:environment] = environments.first
|
83
|
+
end
|
84
|
+
|
72
85
|
end
|
73
86
|
end
|
74
87
|
end
|
@@ -45,9 +45,12 @@ class Chef
|
|
45
45
|
cluster = target.cluster
|
46
46
|
|
47
47
|
ui.info("")
|
48
|
-
ui.info(
|
49
|
-
|
50
|
-
|
48
|
+
ui.info([
|
49
|
+
ui.color("You are in a cluster. There is a sign overhead reading '", :magenta),
|
50
|
+
ui.color(@name_args.first, :yellow, :bold),
|
51
|
+
ui.color("'.\nNext to you a burly man in a greasy apron sharpens his cleaver, \nand a lissom princess performs treacherous origami.", :magenta)
|
52
|
+
].join)
|
53
|
+
ui.info(ui.color("It is Pitch Dark. You are likely to be eaten by a grue.", :black, :bold)) if target.select(&:running?).empty?
|
51
54
|
|
52
55
|
# Commands to try:
|
53
56
|
# nn = Chef::Node.load('node-name')
|
data/lib/gorillib/resolution.rb
CHANGED
@@ -4,7 +4,7 @@ require 'gorillib/hash/deep_merge'
|
|
4
4
|
|
5
5
|
module Gorillib
|
6
6
|
|
7
|
-
# Make a clean deep-copy of the value, via gorillib semantics if
|
7
|
+
# Make a clean deep-copy of the value, via gorillib semantics if
|
8
8
|
# possible, otherwise via marshalling
|
9
9
|
def self.deep_copy(value)
|
10
10
|
case
|
@@ -36,7 +36,7 @@ module Gorillib
|
|
36
36
|
else
|
37
37
|
write_attribute(collection_field_name, coll)
|
38
38
|
end
|
39
|
-
rescue StandardError => err ; err.polish("#{self.class} #{collection_field_name} collection on #{
|
39
|
+
rescue StandardError => err ; err.polish("#{self.class} #{collection_field_name} collection on #{coll}'") rescue nil ; raise ; end
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -44,13 +44,13 @@ module Gorillib
|
|
44
44
|
end
|
45
45
|
|
46
46
|
# The attribute :underlay provides an object (preferably another
|
47
|
-
# Gorillib::Model or the like) that will resolve stacked
|
48
|
-
# defaults. If fields are declared with a :resolver, it will
|
47
|
+
# Gorillib::Model or the like) that will resolve stacked
|
48
|
+
# defaults. If fields are declared with a :resolver, it will
|
49
49
|
# apply that call in preference the default rules (self.field
|
50
50
|
# -> underlay.field -> self.field.default )
|
51
51
|
#
|
52
|
-
# To provide resolve cleanly without read-write loops destroying
|
53
|
-
# the separation of concerns, the resolve mechanism has been
|
52
|
+
# To provide resolve cleanly without read-write loops destroying
|
53
|
+
# the separation of concerns, the resolve mechanism has been
|
54
54
|
# broken from the regular read-write accessors.
|
55
55
|
#
|
56
56
|
module Resolution
|
@@ -59,9 +59,9 @@ module Gorillib
|
|
59
59
|
attr_accessor :underlay
|
60
60
|
|
61
61
|
# Return a fully-resolved copy of this object. All objects
|
62
|
-
# referenced will be clean deep_copies, and will lack the
|
62
|
+
# referenced will be clean deep_copies, and will lack the
|
63
63
|
# :underlay accessor. This is by design, to prevent self-
|
64
|
-
# referential loops (parent->collection->child->owner)
|
64
|
+
# referential loops (parent->collection->child->owner)
|
65
65
|
# when deep_coping.
|
66
66
|
def resolve
|
67
67
|
result = self.class.new
|
@@ -91,7 +91,7 @@ module Gorillib
|
|
91
91
|
end
|
92
92
|
result
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
def resolve_value(value)
|
96
96
|
return if value.nil?
|
97
97
|
return value.resolve if value.respond_to? :resolve
|
@@ -4,9 +4,9 @@ module Ironfan
|
|
4
4
|
class Computer < Builder
|
5
5
|
|
6
6
|
field :server, Ironfan::Dsl::Server
|
7
|
-
collection :resources,
|
8
|
-
collection :drives, Ironfan::Broker::Drive
|
9
|
-
collection :providers,
|
7
|
+
collection :resources, Ironfan::Provider::Resource, :key_method => :name
|
8
|
+
collection :drives, Ironfan::Broker::Drive, :key_method => :name
|
9
|
+
collection :providers, Whatever, :key_method => :name
|
10
10
|
delegate :[], :[]=, :include?, :delete, :to => :resources
|
11
11
|
|
12
12
|
# Only used for bogus servers
|
@@ -21,6 +21,7 @@ module Ironfan
|
|
21
21
|
volumes = server.volumes.values
|
22
22
|
volumes += server.implied_volumes
|
23
23
|
volumes.each { |v| self.drive v.name, :volume => v }
|
24
|
+
rescue StandardError => err ; err.polish("#{self.class} on #{args}'") rescue nil ; raise
|
24
25
|
end
|
25
26
|
|
26
27
|
def name
|
@@ -128,10 +129,6 @@ module Ironfan
|
|
128
129
|
@chef_client_script_content = Ironfan.safely{ File.read(script_filename) }
|
129
130
|
end
|
130
131
|
|
131
|
-
def ssh_identity_file
|
132
|
-
resources[:key_pair].key_filename
|
133
|
-
end
|
134
|
-
|
135
132
|
# def ensure_resource(type)
|
136
133
|
# if type.multiple?
|
137
134
|
# existing = resources[type.resource_id]
|
@@ -182,6 +179,8 @@ module Ironfan
|
|
182
179
|
self[:node]= value
|
183
180
|
end
|
184
181
|
|
182
|
+
def environment ; server && server.environment ; end
|
183
|
+
|
185
184
|
#
|
186
185
|
# client
|
187
186
|
#
|
@@ -200,9 +199,21 @@ module Ironfan
|
|
200
199
|
self[:machine] = value
|
201
200
|
end
|
202
201
|
def dns_name ; machine? ? machine.dns_name : nil ; end
|
203
|
-
def ssh_user ; (server && server.selected_cloud) ? server.selected_cloud.ssh_user : nil ; end
|
204
202
|
def bootstrap_distro ; (server && server.selected_cloud) ? server.selected_cloud.bootstrap_distro : nil ; end
|
205
203
|
|
204
|
+
def keypair
|
205
|
+
resources[:keypair]
|
206
|
+
end
|
207
|
+
|
208
|
+
def ssh_user ; (server && server.selected_cloud) ? server.selected_cloud.ssh_user : nil ; end
|
209
|
+
|
210
|
+
def ssh_identity_file
|
211
|
+
if keypair then keypair.key_filename
|
212
|
+
elsif server && server.selected_cloud then server.selected_cloud.ssh_identity_file(self)
|
213
|
+
else nil
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
206
217
|
#
|
207
218
|
# Status flags
|
208
219
|
#
|
@@ -248,6 +259,14 @@ module Ironfan
|
|
248
259
|
running? || node?
|
249
260
|
end
|
250
261
|
|
262
|
+
def receive_providers(objs)
|
263
|
+
objs = objs.map do |obj|
|
264
|
+
if obj.is_a?(String) then obj = Gorillib::Inflector.constantize(Gorillib::Inflector.camelize(obj.gsub(/\./, '/'))) ; end
|
265
|
+
obj
|
266
|
+
end
|
267
|
+
super(objs)
|
268
|
+
end
|
269
|
+
|
251
270
|
def to_s
|
252
271
|
"<#{self.class}(server=#{server}, resources=#{resources && resources.inspect_compact}, providers=#{providers && providers.inspect_compact})>"
|
253
272
|
end
|
@@ -300,6 +319,10 @@ module Ironfan
|
|
300
319
|
Ironfan.parallel(values) {|c| c.stop }
|
301
320
|
end
|
302
321
|
|
322
|
+
def environments
|
323
|
+
map{|comp| comp.environment }.uniq
|
324
|
+
end
|
325
|
+
|
303
326
|
#
|
304
327
|
# Utility
|
305
328
|
#
|
data/lib/ironfan/broker.rb
CHANGED
@@ -8,10 +8,11 @@ module Ironfan
|
|
8
8
|
end
|
9
9
|
|
10
10
|
class Broker < Builder
|
11
|
-
# Take in a Dsl::Cluster
|
12
|
-
#
|
13
|
-
#
|
11
|
+
# Take in a Dsl::Cluster; return Computers populated with all discovered
|
12
|
+
# resources that correlate; computers corresponding to partial or
|
13
|
+
# unrecognizable resources are labeled as bogus.
|
14
14
|
def discover!(cluster)
|
15
|
+
|
15
16
|
# Get fully resolved servers, and build Computers using them
|
16
17
|
computers = Computers.new(:cluster => cluster)
|
17
18
|
#
|
@@ -22,6 +23,7 @@ module Ironfan
|
|
22
23
|
end
|
23
24
|
#
|
24
25
|
Ironfan.step cluster.name, "Reconciling DSL and provider information", :cyan
|
26
|
+
|
25
27
|
computers.correlate
|
26
28
|
computers.validate
|
27
29
|
#
|
@@ -39,5 +41,4 @@ module Ironfan
|
|
39
41
|
end
|
40
42
|
|
41
43
|
end
|
42
|
-
|
43
44
|
end
|
data/lib/ironfan/dsl/cloud.rb
CHANGED
@@ -4,13 +4,17 @@ module Ironfan
|
|
4
4
|
class Cloud < Ironfan::Dsl
|
5
5
|
magic :default_cloud, :boolean, :default => false
|
6
6
|
|
7
|
-
# Factory out to subclasses
|
8
|
-
def self.receive(obj
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
# Factory out to subclasses
|
8
|
+
def self.receive(obj, &block)
|
9
|
+
if obj.is_a?(Hash)
|
10
|
+
obj = obj.symbolize_keys
|
11
|
+
obj[:_type] ||=
|
12
|
+
case obj[:name]
|
13
|
+
when :ec2 then Ec2
|
14
|
+
when :virtualbox then VirtualBox
|
15
|
+
else raise "Unsupported cloud #{obj[:name]}"
|
16
|
+
end
|
17
|
+
end
|
14
18
|
super
|
15
19
|
end
|
16
20
|
|
@@ -18,4 +22,4 @@ module Ironfan
|
|
18
22
|
end
|
19
23
|
|
20
24
|
end
|
21
|
-
end
|
25
|
+
end
|
data/lib/ironfan/dsl/compute.rb
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
module Ironfan
|
2
2
|
class Dsl
|
3
3
|
|
4
|
+
class RunListItem < Hash
|
5
|
+
Gorillib::Factory.register_factory(self, [self])
|
6
|
+
def name
|
7
|
+
self[:name]
|
8
|
+
end
|
9
|
+
def self.receive(hsh)
|
10
|
+
new.merge!(hsh.symbolize_keys)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
class Compute < Ironfan::Dsl
|
5
15
|
@@run_list_rank = 0
|
6
16
|
field :name, String
|
7
17
|
|
8
18
|
# Resolve each of the following as a merge of their container's attributes and theirs
|
9
|
-
collection :run_list_items,
|
10
|
-
collection :clouds, Ironfan::Dsl::Cloud, :resolver => :merge_resolve
|
11
|
-
collection :volumes, Ironfan::Dsl::Volume, :resolver => :merge_resolve
|
19
|
+
collection :run_list_items, RunListItem, :resolver => :merge_resolve, :key_method => :name
|
20
|
+
collection :clouds, Ironfan::Dsl::Cloud, :resolver => :merge_resolve, :key_method => :name
|
21
|
+
collection :volumes, Ironfan::Dsl::Volume, :resolver => :merge_resolve, :key_method => :name
|
12
22
|
|
13
23
|
# Resolve these normally (overriding on each layer)
|
14
24
|
magic :environment, Symbol, :default => :_default
|
@@ -81,4 +91,4 @@ module Ironfan
|
|
81
91
|
end
|
82
92
|
|
83
93
|
end
|
84
|
-
end
|
94
|
+
end
|
data/lib/ironfan/dsl/ec2.rb
CHANGED
@@ -15,17 +15,17 @@ module Ironfan
|
|
15
15
|
magic :flavor, String, :default => 't1.micro'
|
16
16
|
magic :image_id, String
|
17
17
|
magic :image_name, String
|
18
|
-
magic :keypair,
|
18
|
+
magic :keypair, String
|
19
19
|
magic :monitoring, String
|
20
20
|
magic :mount_ephemerals, Hash, :default => {}
|
21
21
|
magic :permanent, :boolean, :default => false
|
22
22
|
magic :placement_group, String
|
23
|
-
magic :provider,
|
23
|
+
magic :provider, Whatever, :default => Ironfan::Provider::Ec2
|
24
24
|
magic :public_ip, String
|
25
25
|
magic :region, String, :default => ->{ default_region }
|
26
26
|
magic :ssh_user, String, :default => ->{ image_info[:ssh_user] }
|
27
27
|
magic :ssh_identity_dir, String, :default => ->{ Chef::Config.ec2_key_dir }
|
28
|
-
collection :security_groups, Ironfan::Dsl::Ec2::SecurityGroup
|
28
|
+
collection :security_groups, Ironfan::Dsl::Ec2::SecurityGroup, :key_method => :name
|
29
29
|
magic :subnet, String
|
30
30
|
magic :validation_key, String, :default => ->{ IO.read(Chef::Config.validation_key) rescue '' }
|
31
31
|
magic :vpc, String
|
@@ -102,6 +102,14 @@ module Ironfan
|
|
102
102
|
result
|
103
103
|
end
|
104
104
|
|
105
|
+
def receive_provider(obj)
|
106
|
+
if obj.is_a?(String)
|
107
|
+
write_attribute :provider, Gorillib::Inflector.constantize(Gorillib::Inflector.camelize(obj.gsub(/\./, '/')))
|
108
|
+
else
|
109
|
+
super(obj)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
105
113
|
class SecurityGroup < Ironfan::Dsl
|
106
114
|
field :name, String
|
107
115
|
field :group_authorized, Array, :default => []
|
data/lib/ironfan/headers.rb
CHANGED
@@ -46,7 +46,7 @@ module Ironfan
|
|
46
46
|
class EbsVolume < Ironfan::Provider::Resource; end
|
47
47
|
class ElasticIp < Ironfan::Provider::Resource; end
|
48
48
|
class Machine < Ironfan::IaasProvider::Machine; end
|
49
|
-
class
|
49
|
+
class Keypair < Ironfan::Provider::Resource; end
|
50
50
|
class PlacementGroup < Ironfan::Provider::Resource; end
|
51
51
|
class SecurityGroup < Ironfan::Provider::Resource; end
|
52
52
|
end
|
@@ -51,6 +51,7 @@ module Ironfan
|
|
51
51
|
def self.load!(cluster=nil)
|
52
52
|
Ec2.connection.volumes.each do |vol|
|
53
53
|
next if vol.blank?
|
54
|
+
next if %w[deleting deleted error].include?(vol.state.to_s)
|
54
55
|
ebs = EbsVolume.new(:adaptee => vol)
|
55
56
|
# Already have a volume by this name
|
56
57
|
if recall? ebs.name
|
@@ -64,6 +65,11 @@ module Ironfan
|
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
68
|
+
def receive_adaptee(obj)
|
69
|
+
obj = Ec2.connection.volumes.new(obj) if obj.is_a?(Hash)
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
67
73
|
def on_correlate(computer)
|
68
74
|
drive = computer.drive(drivename)
|
69
75
|
drive.disk = self
|
@@ -2,20 +2,22 @@ module Ironfan
|
|
2
2
|
class Provider
|
3
3
|
class Ec2
|
4
4
|
|
5
|
-
class
|
5
|
+
class Keypair < Ironfan::Provider::Resource
|
6
6
|
delegate :_dump, :collection, :collection=, :connection,
|
7
7
|
:connection=, :destroy, :fingerprint, :fingerprint=, :identity,
|
8
8
|
:identity=, :name, :name=, :new_record?, :public_key,
|
9
9
|
:public_key=, :reload, :requires, :requires_one, :save,
|
10
10
|
:symbolize_keys, :wait_for, :writable?, :write,
|
11
11
|
:to => :adaptee
|
12
|
-
field :key_filename, String,
|
13
|
-
:default => ->{ "#{KeyPair.key_dir}/#{name}.pem" }
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
def self.
|
18
|
-
def self.
|
13
|
+
field :key_filename, String, :default => ->{ "#{Keypair.key_dir}/#{name}.pem" }
|
14
|
+
|
15
|
+
def self.shared? ; true ; end
|
16
|
+
def self.multiple? ; false ; end
|
17
|
+
def self.resource_type ; :keypair ; end
|
18
|
+
def self.expected_ids(computer)
|
19
|
+
[computer.server.cluster_name]
|
20
|
+
end
|
19
21
|
|
20
22
|
def private_key
|
21
23
|
File.open(key_filename, "rb").read
|
@@ -39,6 +41,11 @@ module Ironfan
|
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
44
|
+
def receive_adaptee(obj)
|
45
|
+
obj = Ec2.connection.key_pairs.new(obj) if obj.is_a?(Hash)
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
42
49
|
#
|
43
50
|
# Manipulation
|
44
51
|
#
|
@@ -63,6 +70,7 @@ module Ironfan
|
|
63
70
|
warn "Please set 'ec2_key_dir' in your knife.rb. Will use #{dir} as a default"
|
64
71
|
dir
|
65
72
|
end
|
73
|
+
|
66
74
|
end
|
67
75
|
|
68
76
|
end
|
@@ -34,7 +34,6 @@ module Ironfan
|
|
34
34
|
:vpc_id=, :wait_for,
|
35
35
|
:to => :adaptee
|
36
36
|
|
37
|
-
|
38
37
|
def self.shared?() false; end
|
39
38
|
def self.multiple?() false; end
|
40
39
|
# def self.resource_type() Ironfan::IaasProvider::Machine; end
|
@@ -46,7 +45,8 @@ module Ironfan
|
|
46
45
|
tags["Name"] || tags["name"] || id
|
47
46
|
end
|
48
47
|
|
49
|
-
def public_hostname
|
48
|
+
def public_hostname ; dns_name ; end
|
49
|
+
def keypair ; key_pair ; end
|
50
50
|
|
51
51
|
def created?
|
52
52
|
not ['terminated', 'shutting-down'].include? state
|
@@ -104,20 +104,26 @@ module Ironfan
|
|
104
104
|
def self.load!(cluster=nil)
|
105
105
|
Ec2.connection.servers.each do |fs|
|
106
106
|
machine = new(:adaptee => fs)
|
107
|
-
if
|
107
|
+
if (not machine.created?)
|
108
|
+
next unless Ironfan.chef_config[:include_terminated]
|
109
|
+
remember machine, :append_id => "terminated:#{machine.id}"
|
110
|
+
elsif recall? machine.name
|
108
111
|
raise 'duplicate'
|
109
112
|
machine.bogus << :duplicate_machines
|
110
113
|
recall(machine.name).bogus << :duplicate_machines
|
111
114
|
remember machine, :append_id => "duplicate:#{machine.id}"
|
112
|
-
|
115
|
+
else # never seen it
|
113
116
|
remember machine
|
114
|
-
else
|
115
|
-
remember machine, :append_id => "terminated:#{machine.id}"
|
116
117
|
end
|
117
118
|
Chef::Log.debug("Loaded #{machine}")
|
118
119
|
end
|
119
120
|
end
|
120
121
|
|
122
|
+
def receive_adaptee(obj)
|
123
|
+
obj = Ec2.connection.servers.new(obj) if obj.is_a?(Hash)
|
124
|
+
super
|
125
|
+
end
|
126
|
+
|
121
127
|
# Find active machines that haven't matched, but should have,
|
122
128
|
# make sure all bogus machines have a computer to attach to
|
123
129
|
# for display purposes
|
@@ -167,7 +173,7 @@ module Ironfan
|
|
167
173
|
'name' => computer.name,
|
168
174
|
'Name' => computer.name,
|
169
175
|
}
|
170
|
-
Ec2.ensure_tags(tags,computer.machine)
|
176
|
+
Ec2.ensure_tags(tags, computer.machine)
|
171
177
|
|
172
178
|
# register the new volumes for later save!, and tag appropriately
|
173
179
|
computer.machine.volumes.each do |v|
|
@@ -32,6 +32,11 @@ module Ironfan
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
def receive_adaptee(obj)
|
36
|
+
obj = Ec2.connection.security_groups.new(obj) if obj.is_a?(Hash)
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
35
40
|
def to_s
|
36
41
|
if ip_permissions.present?
|
37
42
|
perm_str = ip_permissions.map{|perm|
|
@@ -63,7 +68,12 @@ module Ironfan
|
|
63
68
|
Ironfan.step(computer.server.cluster_name, "creating security groups", :blue)
|
64
69
|
groups.each do |group|
|
65
70
|
Ironfan.step(group, " creating #{group} security group", :blue)
|
66
|
-
|
71
|
+
begin
|
72
|
+
Ec2.connection.create_security_group(group.to_s,"Ironfan created group #{group}")
|
73
|
+
rescue Fog::Compute::AWS::Error => e # InvalidPermission.Duplicate
|
74
|
+
Chef::Log.info("ignoring security group error: #{e}")
|
75
|
+
sleep 0.5 # quit racing so hard
|
76
|
+
end
|
67
77
|
end
|
68
78
|
load! # Get the native groups via reload
|
69
79
|
end
|
@@ -134,7 +144,7 @@ module Ironfan
|
|
134
144
|
begin
|
135
145
|
fog_group.authorize_port_range(range,options)
|
136
146
|
rescue Fog::Compute::AWS::Error => e # InvalidPermission.Duplicate
|
137
|
-
Chef::Log.
|
147
|
+
Chef::Log.info("ignoring #{e}")
|
138
148
|
end
|
139
149
|
end
|
140
150
|
end
|
data/lib/ironfan/provider/ec2.rb
CHANGED
data/lib/ironfan/provider.rb
CHANGED
@@ -6,13 +6,17 @@ module Ironfan
|
|
6
6
|
class Provider < Builder
|
7
7
|
class_attribute :handle
|
8
8
|
|
9
|
-
def self.receive(obj
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def self.receive(obj, &block)
|
10
|
+
if obj.is_a?(Hash)
|
11
|
+
obj = obj.symbolize_keys
|
12
|
+
obj[:_type] =
|
13
|
+
case obj[:name]
|
14
|
+
when :chef then Chef
|
15
|
+
when :ec2 then Ec2
|
16
|
+
when :virtualbox then VirtualBox
|
17
|
+
else raise "Unsupported provider #{obj[:name]}"
|
18
|
+
end
|
19
|
+
end
|
16
20
|
super
|
17
21
|
end
|
18
22
|
|
@@ -50,6 +54,11 @@ module Ironfan
|
|
50
54
|
|
51
55
|
def self.handle ; name.to_s.gsub(/.*::/,'').to_sym ; end
|
52
56
|
|
57
|
+
def self.receive(obj)
|
58
|
+
obj = obj.symbolize_keys if obj.is_a?(Hash)
|
59
|
+
super(obj)
|
60
|
+
end
|
61
|
+
|
53
62
|
#
|
54
63
|
# Flags
|
55
64
|
#
|
data/lib/ironfan/requirements.rb
CHANGED
@@ -2,11 +2,9 @@
|
|
2
2
|
require 'gorillib/builder'
|
3
3
|
require 'gorillib/resolution'
|
4
4
|
|
5
|
-
|
6
5
|
# Pre-declaration of class hierarchy
|
7
6
|
require 'ironfan/headers'
|
8
7
|
|
9
|
-
|
10
8
|
# DSL for cluster descriptions
|
11
9
|
require 'ironfan/dsl'
|
12
10
|
require 'ironfan/builder'
|
@@ -34,7 +32,7 @@ require 'ironfan/provider/chef/role'
|
|
34
32
|
require 'ironfan/provider/ec2'
|
35
33
|
require 'ironfan/provider/ec2/ebs_volume'
|
36
34
|
require 'ironfan/provider/ec2/machine'
|
37
|
-
require 'ironfan/provider/ec2/
|
35
|
+
require 'ironfan/provider/ec2/keypair'
|
38
36
|
require 'ironfan/provider/ec2/placement_group'
|
39
37
|
require 'ironfan/provider/ec2/security_group'
|
40
38
|
|
data/lib/ironfan.rb
CHANGED
@@ -29,7 +29,7 @@ module Ironfan
|
|
29
29
|
raise 'missing block' unless block_given?
|
30
30
|
results = []
|
31
31
|
[targets].flatten.each_with_index.map do |target, idx|
|
32
|
-
sleep(0.
|
32
|
+
sleep(0.25) # avoid hammering with simultaneous requests
|
33
33
|
Thread.new(target) do |target|
|
34
34
|
results[idx] = safely(target.inspect) do
|
35
35
|
yield target
|
@@ -80,19 +80,19 @@ module Ironfan
|
|
80
80
|
# doesn't define the requested cluster.
|
81
81
|
#
|
82
82
|
# @return [Ironfan::Cluster] the requested cluster
|
83
|
-
def self.load_cluster(
|
84
|
-
|
85
|
-
raise ArgumentError, "Please supply a cluster name" if
|
86
|
-
return @@clusters[
|
83
|
+
def self.load_cluster(name)
|
84
|
+
name = name.to_sym
|
85
|
+
raise ArgumentError, "Please supply a cluster name" if name.to_s.empty?
|
86
|
+
return @@clusters[name] if @@clusters[name]
|
87
87
|
|
88
|
-
cluster_file = cluster_filenames[
|
88
|
+
cluster_file = cluster_filenames[name] or raise("Couldn't find a definition for #{name} in cluster_path: #{cluster_path.inspect}")
|
89
89
|
|
90
90
|
Chef::Log.info("Loading cluster #{cluster_file}")
|
91
91
|
|
92
92
|
require cluster_file
|
93
|
-
unless @@clusters[
|
93
|
+
unless @@clusters[name] then die("#{cluster_file} was supposed to have the definition for the #{name} cluster, but didn't") end
|
94
94
|
|
95
|
-
@@clusters[
|
95
|
+
@@clusters[name]
|
96
96
|
end
|
97
97
|
|
98
98
|
#
|
@@ -105,7 +105,7 @@ module Ironfan
|
|
105
105
|
cluster_path.each do |cp_dir|
|
106
106
|
Dir[ File.join(cp_dir, '*.rb') ].each do |filename|
|
107
107
|
cluster_name = File.basename(filename).gsub(/\.rb$/, '')
|
108
|
-
@cluster_filenames[cluster_name] ||= filename
|
108
|
+
@cluster_filenames[cluster_name.to_sym] ||= filename
|
109
109
|
end
|
110
110
|
end
|
111
111
|
@cluster_filenames
|
@@ -149,7 +149,11 @@ module Ironfan
|
|
149
149
|
end
|
150
150
|
|
151
151
|
def self.substep(name, desc)
|
152
|
-
step(name, " - #{desc}", :gray) if
|
152
|
+
step(name, " - #{desc}", :gray) if verbosity >= 1
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.verbosity
|
156
|
+
chef_config[:verbosity].to_i
|
153
157
|
end
|
154
158
|
|
155
159
|
# Output a TODO to the logs if you've switched on pestering
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
ironfan_go!
|
4
|
+
require 'chef/knife/cluster_bootstrap'
|
5
|
+
|
6
|
+
describe Chef::Knife::ClusterBootstrap do
|
7
|
+
let(:cluster) do
|
8
|
+
Ironfan.load_cluster(:gunbai)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:target) do
|
12
|
+
Ironfan.broker.discover!(cluster)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:computers) do
|
16
|
+
Ironfan::Broker::Computers.receive(
|
17
|
+
MultiJson.load(
|
18
|
+
File.open(Pathname.path_to(:fixtures, 'gunbai_slice.json'))))
|
19
|
+
end
|
20
|
+
|
21
|
+
subject do
|
22
|
+
described_class.new(slice)
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'getting slice' do
|
26
|
+
before do
|
27
|
+
subject.stub(:relevant?){ true }
|
28
|
+
subject.stub(:run_bootstrap)
|
29
|
+
subject.config[:yes] = true
|
30
|
+
end
|
31
|
+
context 'full slice' do
|
32
|
+
let(:slice){ ['gunbai'] }
|
33
|
+
it 'fails if there are multiple environments' do
|
34
|
+
expect{ subject.run }.to raise_error("Cannot bootstrap multiple chef environments")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
context 'partial slice' do
|
38
|
+
let(:slice){ ['gunbai-hub'] }
|
39
|
+
it 'runs' do
|
40
|
+
subject.should_receive(:run_bootstrap).once
|
41
|
+
subject.run
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
# it 'loads computers from json' do
|
48
|
+
# computers.length.should == 2
|
49
|
+
# computers.first.server.fullname.should == 'gunbai-hub-0'
|
50
|
+
# end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Ironfan.cluster 'gunbai' do
|
2
|
+
cloud(:ec2) do
|
3
|
+
permanent false
|
4
|
+
availability_zones ['us-east-1d']
|
5
|
+
flavor 't1.micro'
|
6
|
+
backing 'ebs'
|
7
|
+
image_name 'natty'
|
8
|
+
bootstrap_distro 'ubuntu10.04-ironfan'
|
9
|
+
chef_client_script 'client.rb'
|
10
|
+
mount_ephemerals
|
11
|
+
end
|
12
|
+
|
13
|
+
environment :dev
|
14
|
+
|
15
|
+
role :ssh
|
16
|
+
cloud(:ec2).security_group(:ssh).authorize_port_range(22..22)
|
17
|
+
|
18
|
+
facet :hub do
|
19
|
+
end
|
20
|
+
|
21
|
+
facet :spoke do
|
22
|
+
environment :other
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,330 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"server": {
|
4
|
+
"name": "0",
|
5
|
+
"run_list_items": [
|
6
|
+
{
|
7
|
+
"name": "role[ssh]",
|
8
|
+
"rank": 1,
|
9
|
+
"placement": "normal"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"name": "role[gunbai_cluster]",
|
13
|
+
"rank": 2,
|
14
|
+
"placement": "last"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"name": "role[gunbai_hub]",
|
18
|
+
"rank": 3,
|
19
|
+
"placement": "last"
|
20
|
+
}
|
21
|
+
],
|
22
|
+
"clouds": [
|
23
|
+
{
|
24
|
+
"name": "ec2",
|
25
|
+
"default_cloud": false,
|
26
|
+
"availability_zones": [
|
27
|
+
"us-east-1d"
|
28
|
+
],
|
29
|
+
"backing": "ebs",
|
30
|
+
"bits": 64,
|
31
|
+
"bootstrap_distro": "ubuntu10.04-ironfan",
|
32
|
+
"chef_client_script": "client.rb",
|
33
|
+
"default_availability_zone": "us-east-1d",
|
34
|
+
"flavor": "t1.micro",
|
35
|
+
"image_id": null,
|
36
|
+
"image_name": "natty",
|
37
|
+
"keypair": null,
|
38
|
+
"monitoring": null,
|
39
|
+
"mount_ephemerals": {
|
40
|
+
|
41
|
+
},
|
42
|
+
"permanent": false,
|
43
|
+
"placement_group": null,
|
44
|
+
"provider": "Ironfan::Provider::Ec2",
|
45
|
+
"public_ip": null,
|
46
|
+
"region": "us-east-1",
|
47
|
+
"ssh_user": "ubuntu",
|
48
|
+
"ssh_identity_dir": "/Users/flip/ics/sysadmin/enterprise-homebase/knife/credentials/ec2_keys",
|
49
|
+
"security_groups": [
|
50
|
+
{
|
51
|
+
"name": "ssh",
|
52
|
+
"group_authorized": [
|
53
|
+
|
54
|
+
],
|
55
|
+
"group_authorized_by": [
|
56
|
+
|
57
|
+
],
|
58
|
+
"range_authorizations": [
|
59
|
+
[
|
60
|
+
"22..22",
|
61
|
+
"0.0.0.0/0",
|
62
|
+
"tcp"
|
63
|
+
]
|
64
|
+
],
|
65
|
+
"_type": "ironfan.dsl.ec2.security_group"
|
66
|
+
}
|
67
|
+
],
|
68
|
+
"subnet": null,
|
69
|
+
"validation_key": "-----BEGIN RSA PRIVATE KEY-----\nSNIP\n-----END RSA PRIVATE KEY-----\n",
|
70
|
+
"vpc": null,
|
71
|
+
"_type": "ironfan.dsl.ec2"
|
72
|
+
}
|
73
|
+
],
|
74
|
+
"volumes": [
|
75
|
+
|
76
|
+
],
|
77
|
+
"environment": "dev",
|
78
|
+
"use_cloud": null,
|
79
|
+
"cluster_role": {
|
80
|
+
"name": "gunbai_cluster",
|
81
|
+
"override_attributes": {
|
82
|
+
|
83
|
+
},
|
84
|
+
"default_attributes": {
|
85
|
+
|
86
|
+
},
|
87
|
+
"_type": "ironfan.dsl.role"
|
88
|
+
},
|
89
|
+
"facet_role": {
|
90
|
+
"name": "gunbai_hub",
|
91
|
+
"override_attributes": {
|
92
|
+
|
93
|
+
},
|
94
|
+
"default_attributes": {
|
95
|
+
|
96
|
+
},
|
97
|
+
"_type": "ironfan.dsl.role"
|
98
|
+
},
|
99
|
+
"cluster_name": "gunbai",
|
100
|
+
"facet_name": "hub",
|
101
|
+
"_type": "ironfan.dsl.server"
|
102
|
+
},
|
103
|
+
"resources": [
|
104
|
+
{
|
105
|
+
"adaptee": {"name":"gunbai","fingerprint":"a2:9a:15:b3:bc:95:68:99:2c:91:43:9c:3b:6b:99:00:11:e9:b2:5e"},
|
106
|
+
"bogus": [
|
107
|
+
|
108
|
+
],
|
109
|
+
"key_filename": "/Users/flip/ics/sysadmin/enterprise-homebase/knife/credentials/ec2_keys/gunbai.pem",
|
110
|
+
"_type": "ironfan.provider.ec2.keypair"
|
111
|
+
},
|
112
|
+
{
|
113
|
+
"adaptee": {"ip_permissions":[{"groups":[],"ipRanges":[{"cidrIp":"0.0.0.0/0"}],"ipProtocol":"tcp","fromPort":22,"toPort":22}],"ip_permissions_egress":[],"owner_id":"689981200839","group_id":"sg-a0f174c9","name":"ssh","description":"cluster_chef+generated+group+ssh"},
|
114
|
+
"bogus": [
|
115
|
+
|
116
|
+
],
|
117
|
+
"ensured": false,
|
118
|
+
"_type": "ironfan.provider.ec2.security_group"
|
119
|
+
}
|
120
|
+
],
|
121
|
+
"drives": [
|
122
|
+
{
|
123
|
+
"node": {
|
124
|
+
|
125
|
+
},
|
126
|
+
"disk": null,
|
127
|
+
"volume": {
|
128
|
+
"name": "root",
|
129
|
+
"attachable": "ebs",
|
130
|
+
"availability_zone": null,
|
131
|
+
"create_at_launch": false,
|
132
|
+
"device": "/dev/sda1",
|
133
|
+
"formattable": false,
|
134
|
+
"fstype": "ext4",
|
135
|
+
"in_raid": false,
|
136
|
+
"keep": false,
|
137
|
+
"mount_dump": null,
|
138
|
+
"mount_pass": null,
|
139
|
+
"mount_options": "defaults,nouuid,noatime",
|
140
|
+
"mount_point": "/",
|
141
|
+
"mountable": true,
|
142
|
+
"size": null,
|
143
|
+
"volume_id": null,
|
144
|
+
"resizable": false,
|
145
|
+
"snapshot_id": null,
|
146
|
+
"snapshot_name": null,
|
147
|
+
"tags": {
|
148
|
+
|
149
|
+
},
|
150
|
+
"_type": "ironfan.dsl.volume"
|
151
|
+
},
|
152
|
+
"name": "root",
|
153
|
+
"_type": "ironfan.broker.drive"
|
154
|
+
}
|
155
|
+
],
|
156
|
+
"providers": [
|
157
|
+
"Ironfan::Provider::ChefServer",
|
158
|
+
"Ironfan::Provider::Ec2"
|
159
|
+
],
|
160
|
+
"name": null,
|
161
|
+
"bogus": [
|
162
|
+
|
163
|
+
],
|
164
|
+
"_type": "ironfan.broker.computer"
|
165
|
+
},
|
166
|
+
{
|
167
|
+
"server": {
|
168
|
+
"name": "0",
|
169
|
+
"run_list_items": [
|
170
|
+
{
|
171
|
+
"name": "role[ssh]",
|
172
|
+
"rank": 1,
|
173
|
+
"placement": "normal"
|
174
|
+
},
|
175
|
+
{
|
176
|
+
"name": "role[gunbai_cluster]",
|
177
|
+
"rank": 4,
|
178
|
+
"placement": "last"
|
179
|
+
},
|
180
|
+
{
|
181
|
+
"name": "role[gunbai_spoke]",
|
182
|
+
"rank": 5,
|
183
|
+
"placement": "last"
|
184
|
+
}
|
185
|
+
],
|
186
|
+
"clouds": [
|
187
|
+
{
|
188
|
+
"name": "ec2",
|
189
|
+
"default_cloud": false,
|
190
|
+
"availability_zones": [
|
191
|
+
"us-east-1d"
|
192
|
+
],
|
193
|
+
"backing": "ebs",
|
194
|
+
"bits": 64,
|
195
|
+
"bootstrap_distro": "ubuntu10.04-ironfan",
|
196
|
+
"chef_client_script": "client.rb",
|
197
|
+
"default_availability_zone": "us-east-1d",
|
198
|
+
"flavor": "t1.micro",
|
199
|
+
"image_id": null,
|
200
|
+
"image_name": "natty",
|
201
|
+
"keypair": null,
|
202
|
+
"monitoring": null,
|
203
|
+
"mount_ephemerals": {
|
204
|
+
|
205
|
+
},
|
206
|
+
"permanent": false,
|
207
|
+
"placement_group": null,
|
208
|
+
"provider": "Ironfan::Provider::Ec2",
|
209
|
+
"public_ip": null,
|
210
|
+
"region": "us-east-1",
|
211
|
+
"ssh_user": "ubuntu",
|
212
|
+
"ssh_identity_dir": "/Users/flip/ics/sysadmin/enterprise-homebase/knife/credentials/ec2_keys",
|
213
|
+
"security_groups": [
|
214
|
+
{
|
215
|
+
"name": "ssh",
|
216
|
+
"group_authorized": [
|
217
|
+
|
218
|
+
],
|
219
|
+
"group_authorized_by": [
|
220
|
+
|
221
|
+
],
|
222
|
+
"range_authorizations": [
|
223
|
+
[
|
224
|
+
"22..22",
|
225
|
+
"0.0.0.0/0",
|
226
|
+
"tcp"
|
227
|
+
]
|
228
|
+
],
|
229
|
+
"_type": "ironfan.dsl.ec2.security_group"
|
230
|
+
}
|
231
|
+
],
|
232
|
+
"subnet": null,
|
233
|
+
"validation_key": "-----BEGIN RSA PRIVATE KEY-----\nSNIP\n-----END RSA PRIVATE KEY-----\n",
|
234
|
+
"vpc": null,
|
235
|
+
"_type": "ironfan.dsl.ec2"
|
236
|
+
}
|
237
|
+
],
|
238
|
+
"volumes": [
|
239
|
+
|
240
|
+
],
|
241
|
+
"environment": "dev",
|
242
|
+
"use_cloud": null,
|
243
|
+
"cluster_role": {
|
244
|
+
"name": "gunbai_cluster",
|
245
|
+
"override_attributes": {
|
246
|
+
|
247
|
+
},
|
248
|
+
"default_attributes": {
|
249
|
+
|
250
|
+
},
|
251
|
+
"_type": "ironfan.dsl.role"
|
252
|
+
},
|
253
|
+
"facet_role": {
|
254
|
+
"name": "gunbai_spoke",
|
255
|
+
"override_attributes": {
|
256
|
+
|
257
|
+
},
|
258
|
+
"default_attributes": {
|
259
|
+
|
260
|
+
},
|
261
|
+
"_type": "ironfan.dsl.role"
|
262
|
+
},
|
263
|
+
"cluster_name": "gunbai",
|
264
|
+
"facet_name": "spoke",
|
265
|
+
"_type": "ironfan.dsl.server"
|
266
|
+
},
|
267
|
+
"resources": [
|
268
|
+
{
|
269
|
+
"adaptee": {"name":"gunbai","fingerprint":"a2:3b:9a:15:b3:bc:95:68:99:9e:2c:91:43:9c:6b:a5:6f:e9:b2:5e"},
|
270
|
+
"bogus": [
|
271
|
+
|
272
|
+
],
|
273
|
+
"key_filename": "/Users/flip/ics/sysadmin/enterprise-homebase/knife/credentials/ec2_keys/gunbai.pem",
|
274
|
+
"_type": "ironfan.provider.ec2.keypair"
|
275
|
+
},
|
276
|
+
{
|
277
|
+
"adaptee": {"ip_permissions":[{"groups":[],"ipRanges":[{"cidrIp":"0.0.0.0/0"}],"ipProtocol":"tcp","fromPort":22,"toPort":22}],"ip_permissions_egress":[],"owner_id":"689981200839","group_id":"sg-a0f174c9","name":"ssh","description":"cluster_chef+generated+group+ssh"},
|
278
|
+
"bogus": [
|
279
|
+
|
280
|
+
],
|
281
|
+
"ensured": false,
|
282
|
+
"_type": "ironfan.provider.ec2.security_group"
|
283
|
+
}
|
284
|
+
],
|
285
|
+
"drives": [
|
286
|
+
{
|
287
|
+
"node": {
|
288
|
+
|
289
|
+
},
|
290
|
+
"disk": null,
|
291
|
+
"volume": {
|
292
|
+
"name": "root",
|
293
|
+
"attachable": "ebs",
|
294
|
+
"availability_zone": null,
|
295
|
+
"create_at_launch": false,
|
296
|
+
"device": "/dev/sda1",
|
297
|
+
"formattable": false,
|
298
|
+
"fstype": "ext4",
|
299
|
+
"in_raid": false,
|
300
|
+
"keep": false,
|
301
|
+
"mount_dump": null,
|
302
|
+
"mount_pass": null,
|
303
|
+
"mount_options": "defaults,nouuid,noatime",
|
304
|
+
"mount_point": "/",
|
305
|
+
"mountable": true,
|
306
|
+
"size": null,
|
307
|
+
"volume_id": null,
|
308
|
+
"resizable": false,
|
309
|
+
"snapshot_id": null,
|
310
|
+
"snapshot_name": null,
|
311
|
+
"tags": {
|
312
|
+
|
313
|
+
},
|
314
|
+
"_type": "ironfan.dsl.volume"
|
315
|
+
},
|
316
|
+
"name": "root",
|
317
|
+
"_type": "ironfan.broker.drive"
|
318
|
+
}
|
319
|
+
],
|
320
|
+
"providers": [
|
321
|
+
"Ironfan::Provider::ChefServer",
|
322
|
+
"Ironfan::Provider::Ec2"
|
323
|
+
],
|
324
|
+
"name": null,
|
325
|
+
"bogus": [
|
326
|
+
|
327
|
+
],
|
328
|
+
"_type": "ironfan.broker.computer"
|
329
|
+
}
|
330
|
+
]
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'ironfan'
|
4
|
+
|
5
|
+
describe Ironfan::Dsl::Cluster do
|
6
|
+
let (:cluster) do
|
7
|
+
Ironfan.cluster "sparky" do
|
8
|
+
|
9
|
+
cloud(:ec2) do
|
10
|
+
security_group(:ssh).authorize_port_range 22..22
|
11
|
+
flavor 't1.micro'
|
12
|
+
end
|
13
|
+
|
14
|
+
facet :web do
|
15
|
+
instances 3
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'web facet server resolution' do
|
22
|
+
before { @facet = cluster.facets.values.first }
|
23
|
+
subject { @facet }
|
24
|
+
its(:name) { should eql "web" }
|
25
|
+
|
26
|
+
it 'should have the right number of servers' do
|
27
|
+
@facet.servers.length.should == 3
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should have one cloud provider, EC2' do
|
31
|
+
@facet.servers[0].clouds.keys.should == [ :ec2 ]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,31 @@ $:.unshift File.expand_path('../../lib', __FILE__)
|
|
2
2
|
require 'chef'
|
3
3
|
require 'chef/knife'
|
4
4
|
require 'fog'
|
5
|
-
|
6
5
|
Fog.mock!
|
7
6
|
Fog::Mock.delay = 0
|
7
|
+
|
8
|
+
require 'gorillib/pathname'
|
9
|
+
|
10
|
+
Pathname.register_paths(
|
11
|
+
code: File.expand_path('../..', __FILE__),
|
12
|
+
fixtures: [:code, 'spec', 'fixtures'],
|
13
|
+
)
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
def ironfan_go!
|
17
|
+
Chef::Knife.new.configure_chef
|
18
|
+
Chef::Config.instance_eval do
|
19
|
+
knife.merge!({
|
20
|
+
:aws_access_key_id => 'access_key',
|
21
|
+
:aws_secret_access_key => 'secret',
|
22
|
+
})
|
23
|
+
cluster_path Pathname.path_to(:fixtures).to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'ironfan'
|
27
|
+
|
28
|
+
Ironfan.ui = Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
|
29
|
+
Ironfan.chef_config = { :verbosity => 0 }
|
30
|
+
Ironfan.cluster_path
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ironfan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 4.2.
|
5
|
+
version: 4.2.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Infochimps
|
@@ -203,14 +203,18 @@ files:
|
|
203
203
|
- lib/ironfan/provider/ec2.rb
|
204
204
|
- lib/ironfan/provider/ec2/ebs_volume.rb
|
205
205
|
- lib/ironfan/provider/ec2/elastic_ip.rb
|
206
|
-
- lib/ironfan/provider/ec2/
|
206
|
+
- lib/ironfan/provider/ec2/keypair.rb
|
207
207
|
- lib/ironfan/provider/ec2/machine.rb
|
208
208
|
- lib/ironfan/provider/ec2/placement_group.rb
|
209
209
|
- lib/ironfan/provider/ec2/security_group.rb
|
210
210
|
- lib/ironfan/provider/virtualbox.rb
|
211
211
|
- lib/ironfan/provider/virtualbox/machine.rb
|
212
212
|
- lib/ironfan/requirements.rb
|
213
|
+
- spec/chef/cluster_bootstrap_spec.rb
|
214
|
+
- spec/fixtures/gunbai.rb
|
215
|
+
- spec/fixtures/gunbai_slice.json
|
213
216
|
- spec/ironfan/cluster_spec.rb
|
217
|
+
- spec/ironfan/ec2/cloud_provider.rb
|
214
218
|
- spec/ironfan/ec2/cloud_provider_spec.rb
|
215
219
|
- spec/ironfan/ec2/security_group_spec.rb
|
216
220
|
- spec/spec_helper.rb
|
@@ -230,7 +234,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
230
234
|
requirements:
|
231
235
|
- - ">="
|
232
236
|
- !ruby/object:Gem::Version
|
233
|
-
hash:
|
237
|
+
hash: 3459217144726680577
|
234
238
|
segments:
|
235
239
|
- 0
|
236
240
|
version: "0"
|
@@ -252,5 +256,9 @@ test_files:
|
|
252
256
|
- spec/ironfan/cluster_spec.rb
|
253
257
|
- spec/ironfan/ec2/cloud_provider_spec.rb
|
254
258
|
- spec/ironfan/ec2/security_group_spec.rb
|
259
|
+
- spec/ironfan/ec2/cloud_provider.rb
|
260
|
+
- spec/chef/cluster_bootstrap_spec.rb
|
261
|
+
- spec/fixtures/gunbai_slice.json
|
262
|
+
- spec/fixtures/gunbai.rb
|
255
263
|
- spec/spec_helper.rb
|
256
264
|
- spec/test_config.rb
|