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
data/lib/ironfan.rb CHANGED
@@ -1,235 +1,170 @@
1
1
  require 'ironfan/requirements'
2
2
 
3
3
  module Ironfan
4
- @@clusters ||= Hash.new
5
- @@realms ||= Hash.new
6
-
7
- # path to search for cluster definition files
8
- def self.cluster_path
9
- return Array(Chef::Config[:cluster_path]) if Chef::Config[:cluster_path]
10
- raise "Holy smokes, you have no cookbook_path or cluster_path set up. Follow chef's directions for creating a knife.rb." if Chef::Config[:cookbook_path].blank?
11
- cl_path = Chef::Config[:cookbook_path].map{|dir| File.expand_path('../clusters', dir) }.uniq
12
- ui.warn "No cluster path set. Taking a wild guess that #{cl_path.inspect} is \nreasonable based on your cookbook_path -- but please set cluster_path in your knife.rb"
13
- Chef::Config[:cluster_path] = cl_path
14
- end
4
+ module_function
15
5
 
16
6
  #
17
- # Delegates
18
- def self.clusters
19
- @@clusters
7
+ # Attributes
8
+ #
9
+ def clusters
10
+ Ironfan::Dsl::Cluster.definitions
20
11
  end
21
12
 
22
- #
23
- # Delegates
24
- def self.realms
25
- @@realms
13
+ def realms
14
+ Ironfan::Dsl::Realm.definitions
26
15
  end
27
16
 
28
- def self.ui=(ui) @ui = ui ; end
29
- def self.ui() @ui ; end
17
+ def ui=(ui) @ui = ui ; end
18
+ def ui() @ui ; end
30
19
 
31
- def self.chef_config=(cc) @chef_config = cc ; end
32
- def self.chef_config() @chef_config ; end
20
+ def chef_config=(cc) @chef_config = cc ; end
21
+ def chef_config() @chef_config ; end
33
22
 
34
- # execute against multiple targets in parallel
35
- def self.parallel(targets)
36
- raise 'missing block' unless block_given?
37
- results = []
38
- [targets].flatten.each_with_index.map do |target, idx|
39
- sleep(0.25) # avoid hammering with simultaneous requests
40
- Thread.new(target) do |target|
41
- results[idx] = safely(target.inspect) do
42
- yield target
43
- end
44
- end
45
- end.each(&:join) # wait for all the blocks to return
46
- results
47
- end
23
+ def knife_config=(kc) @knife_config = kc ; end
24
+ def knife_config() @knife_config ; end
48
25
 
49
26
  #
50
- # Defines a cluster with the given name.
27
+ # Dsl constructors
51
28
  #
52
- # @example
53
- # Ironfan.cluster 'demosimple' do
54
- # cloud :ec2 do
55
- # availability_zones ['us-east-1d']
56
- # flavor "t1.micro"
57
- # image_name "ubuntu-natty"
58
- # end
59
- # role :base_role
60
- # role :chef_client
61
- #
62
- # facet :sandbox do
63
- # instances 2
64
- # role :nfs_client
65
- # end
66
- # end
67
- #
68
- #
69
- def self.cluster(name, attrs={}, &block)
70
- name = name.to_sym
71
- # If this is being called as Ironfan.cluster('foo') with no additional arguments,
72
- # return the cached cluster object if it exists
73
- if @@clusters[name] and attrs.empty? and not block_given?
74
- return @@clusters[name]
75
- else # Otherwise we're being asked to (re)initialize and cache a cluster definition
76
- cl = Ironfan::Dsl::Cluster.new(:name => name)
77
- cl.receive!(attrs, &block)
78
- @@clusters[name] = cl.resolve
29
+ def cluster(name, attrs = {}, &blk)
30
+ existing = clusters[name.to_sym]
31
+ return existing if attrs.empty? && !block_given?
32
+ if existing
33
+ existing.receive!(attrs, &blk)
34
+ # existing.resolve!
35
+ else
36
+ cl = Ironfan::Dsl::Cluster.define(attrs.merge(name: name.to_sym), &blk)
37
+ # cl.resolve!
79
38
  end
80
39
  end
81
40
 
82
- def self.realm(name, attrs={}, &block)
83
- name = name.to_sym
84
- if @@realms[name] and attrs.empty? and not block_given?
85
- return @@realms[name]
41
+ def realm(name, attrs = {}, &blk)
42
+ existing = realms[name.to_sym]
43
+ return existing if attrs.empty? && !block_given?
44
+ if existing
45
+ existing.receive!(attrs, &blk)
46
+ # existing.resolve!
86
47
  else
87
- rlm = Ironfan::Dsl::Realm.new(:name => name)
88
- rlm.receive!(attrs, &block)
89
- rlm.clusters.keys.each{|k| @@clusters[k.to_sym] = rlm.clusters[k].resolve}
90
- @@realms[name] = rlm
48
+ rlm = Ironfan::Dsl::Realm.define(attrs.merge(name: name.to_sym), &blk)
49
+ # rlm.resolve!
91
50
  end
92
51
  end
93
52
 
94
- def self.load_realm(name)
95
- name = name.to_sym
96
- raise ArgumentError, "Please supply a realm name" if name.to_s.empty?
97
- return @@realms[name] if @@realms[name]
98
-
99
- load_cluster_files
100
-
101
- unless @@realms[name] then die("Couldn't find a realm definition for #{name} in #{cluster_path}") end
102
-
103
- @@realms[name]
104
- end
105
-
106
- #
107
- # Return cluster if it's defined. Otherwise, search Ironfan.cluster_path
108
- # for an eponymous file, load it, and return the cluster it defines.
109
53
  #
110
- # Raises an error if a matching file isn't found, or if loading that file
111
- # doesn't define the requested cluster.
54
+ # Dsl loaders
112
55
  #
113
- # @return [Ironfan::Cluster] the requested cluster
114
- def self.load_cluster(name)
115
- name = name.to_sym
116
- raise ArgumentError, "Please supply a cluster name" if name.to_s.empty?
117
- return @@clusters[name] if @@clusters[name]
56
+ def clusters_dir
57
+ return Array(chef_config[:cluster_path]) if chef_config[:cluster_path]
58
+ raise "Holy smokes, you have no cookbook_path or cluster_path set up. Follow chef's directions for creating a knife.rb." if chef_config[:cookbook_path].blank?
59
+ cl_path = chef_config[:cookbook_path].map{|dir| File.expand_path('../clusters', dir) }.uniq
60
+ ui.warn "No cluster path set. Taking a wild guess that #{cl_path.inspect} is \nreasonable based on your cookbook_path -- but please set cluster_path in your knife.rb"
61
+ chef_config[:cluster_path] = cl_path
62
+ end
118
63
 
119
- load_cluster_files
64
+ def realms_dir
65
+ clusters_dir.map{ |dir| File.expand_path('../realms', dir) }.uniq
66
+ end
120
67
 
121
- unless @@clusters[name] then die("Couldn't find a cluster definition for #{name} in #{cluster_path}") end
68
+ def load_cluster name
69
+ raise ArgumentError.new('Please supply a cluster name') if name.blank?
70
+ load_dsl_definition(name, clusters_dir)
71
+ clusters[name.to_sym] or die("Couldn't find a cluster definition for <#{name}> in #{clusters_dir}")
72
+ end
122
73
 
123
- @@clusters[name]
74
+ def load_realm name
75
+ raise ArgumentError.new('Please supply a realm name') if name.blank?
76
+ load_dsl_definition(name, realms_dir)
77
+ realms[name.to_sym] or die("Couldn't find a realm definition for <#{name}> in #{realms_dir}")
124
78
  end
125
79
 
126
- def self.load_cluster_files
127
- cluster_path.each do |cp_dir|
128
- Dir[ File.join(cp_dir, '*.rb') ].each do |filename|
129
- Chef::Log.info("Loading cluster file #{filename}")
130
- require filename
131
- clusters.values.each{|cluster| cluster.source_file ||= filename}
132
- end
80
+ def load_dsl_definition(name, location)
81
+ Chef::Log.info "Looking for <#{name}> dsl definition in #{location}"
82
+ if named_file = dsl_files(location).detect{ |dsl_file| File.basename(dsl_file, '.rb') == name }
83
+ load_dsl_file named_file
84
+ else
85
+ dsl_files(location).each{ |f| load_dsl_file f }
133
86
  end
134
87
  end
135
88
 
136
- #
137
- # Map from cluster name to file name
138
- #
139
- # @return [Hash] map from cluster name to file name
140
- def self.cluster_filenames
141
- return @cluster_filenames if @cluster_filenames
142
- @cluster_filenames = {}
143
- cluster_path.each do |cp_dir|
144
- Dir[ File.join(cp_dir, '*.rb') ].each do |filename|
145
- cluster_name = File.basename(filename).gsub(/\.rb$/, '')
146
- @cluster_filenames[cluster_name.to_sym] ||= filename
147
- end
148
- end
149
- @cluster_filenames
89
+ def dsl_files location
90
+ Dir.glob File.join(location, '**/*.rb')
91
+ end
92
+
93
+ def load_dsl_file filename
94
+ Chef::Log.info "Loading dsl file #{filename}"
95
+ require filename
150
96
  end
151
97
 
152
98
  #
153
- # Utility to die with an error message.
154
- # If the last arg is an integer, use it as the exit code.
99
+ # Common utility methods
155
100
  #
156
- def self.die *strings
157
- exit_code = strings.last.is_a?(Integer) ? strings.pop : -1
158
- strings.each{|str| ui.warn str }
101
+ def die(*messages)
102
+ exit_code = messages.last.is_a?(Integer) ? messages.pop : -1
103
+ messages.each{ |msg| ui.warn msg }
159
104
  exit exit_code
160
105
  end
161
106
 
162
- #
163
- # Utility to turn an error into a warning
164
- #
165
- # @example
166
- # Ironfan.safely do
167
- # Ironfan.fog_connection.associate_address(self.fog_server.id, address)
168
- # end
169
- #
170
- def self.safely(info="")
107
+ def parallel(targets, &actions)
108
+ raise ArgumentError.new('Must provide a block to run in parallel') unless block_given?
109
+ results = []
110
+ [targets].flatten.each_with_index.map do |target, idx|
111
+ sleep(0.25) # avoid hammering with simultaneous requests
112
+ Thread.new(target) do |target|
113
+ results[idx] = safely(target.inspect) do
114
+ yield target
115
+ end
116
+ end
117
+ end.each(&:join) # wait for all the blocks to return
118
+ results
119
+ end
120
+
121
+ def safely(operation = '', &action)
171
122
  begin
172
123
  yield
173
124
  rescue StandardError => err
174
- ui.warn("Error running #{info}:")
175
- ui.warn(err)
176
- Chef::Log.error( err )
177
- Chef::Log.error( err.backtrace.join("\n") )
125
+ ui.warn "Error running #{operation}:"
126
+ ui.warn err
127
+ Chef::Log.error err
128
+ Chef::Log.error err.backtrace.join("\n")
178
129
  return err
179
130
  end
180
131
  end
181
132
 
182
- #
183
- # Utility to retry a flaky operation three times, with ascending wait times
184
- #
185
- # FIXME: Add specs to test the rescue here. It's a PITA to debug naturally or
186
- #
187
- # Manual test:
188
- # bundle exec ruby -e "require 'chef'; require 'ironfan'; Ironfan.tell_you_thrice { p 'hah'; raise 'hell' }"
189
- def self.tell_you_thrice(options={})
190
- options = { name: "problem",
191
- error_class: StandardError,
192
- retries: 3,
193
- multiplier: 3 }.merge!(options)
194
- try = 0
195
- message = ''
133
+ def tell_you_thrice(options = {}, &action)
134
+ error_class = options[:error_class] || StandardError
135
+ retries = options[:retries] || 3
136
+ multiplier = options[:multiplier] || 3
196
137
 
138
+ attempt = 0
197
139
  begin
198
- try += 1
140
+ attempt += 1
199
141
  yield
200
- rescue options[:error_class] => err
201
- raise unless try < options[:retries]
202
- pause_for = options[:multiplier] * try
142
+ rescue error_class => err
143
+ raise if attempt > retries
144
+ pause_for = multiplier * attempt
203
145
  Chef::Log.debug "Caught error (was #{err.inspect}). Sleeping #{pause_for} seconds."
204
146
  sleep pause_for
205
147
  retry
206
148
  end
207
149
  end
208
150
 
209
- #
210
- # Utility to show a step of the overall process
211
- #
212
- def self.step(name, desc, *style)
151
+ def step(name, desc, *style)
213
152
  ui.info(" #{"%-15s" % (name.to_s+":")}\t#{ui.color(desc.to_s, *style)}")
214
153
  end
215
154
 
216
- def self.substep(name, desc, color = :gray)
155
+ def substep(name, desc, color = :gray)
217
156
  step(name, " - #{desc}", color) if (verbosity >= 1 or color != :gray)
218
157
  end
219
158
 
220
- def self.verbosity
221
- chef_config[:verbosity].to_i
159
+ def verbosity
160
+ knife_config[:verbosity].to_i
222
161
  end
223
162
 
224
- # Output a TODO to the logs if you've switched on pestering
225
- def self.todo(*args)
226
- Chef::Log.debug(*args) if Chef::Config[:show_todo]
163
+ def todo(*args)
164
+ Chef::Log.debug(*args) if knife_config[:show_todo]
227
165
  end
228
166
 
229
- #
230
- # Utility to do mock out a step during a dry-run
231
- #
232
- def self.unless_dry_run
167
+ def unless_dry_run(&action)
233
168
  if dry_run?
234
169
  ui.info(" ... but not really")
235
170
  return nil
@@ -237,12 +172,12 @@ module Ironfan
237
172
  yield
238
173
  end
239
174
  end
240
- def self.dry_run?
241
- chef_config[:dry_run]
175
+
176
+ def dry_run?
177
+ knife_config[:dry_run]
242
178
  end
243
179
 
244
- # Intentionally skipping an implied step
245
- def self.noop(source,method,*params)
180
+ def noop(source, method, *params)
246
181
  # Chef::Log.debug("#{method} is a no-op for #{source} -- skipping (#{params.join(',')})")
247
182
  end
248
183
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  ironfan_go!
4
- require 'chef/knife/cluster_bootstrap'
5
4
 
6
5
  describe Chef::Knife::ClusterBootstrap do
7
6
  let(:cluster) do
@@ -29,13 +28,13 @@ describe Chef::Knife::ClusterBootstrap do
29
28
  subject.config[:yes] = true
30
29
  end
31
30
  context 'full slice' do
32
- let(:slice){ ['gunbai'] }
31
+ let(:slice){ ['samurai-gunbai'] }
33
32
  it 'fails if there are multiple environments' do
34
33
  expect{ subject.run }.to raise_error("Cannot bootstrap multiple chef environments")
35
34
  end
36
35
  end
37
36
  context 'partial slice' do
38
- let(:slice){ ['gunbai-hub'] }
37
+ let(:slice){ ['samurai-gunbai-hub'] }
39
38
  it 'runs' do
40
39
  subject.should_receive(:run_bootstrap).once
41
40
  subject.run
@@ -44,8 +43,4 @@ describe Chef::Knife::ClusterBootstrap do
44
43
 
45
44
  end
46
45
 
47
- # it 'loads computers from json' do
48
- # computers.length.should == 2
49
- # computers.first.server.full_name.should == 'gunbai-hub-0'
50
- # end
51
46
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  ironfan_go!
4
- require 'chef/knife/cluster_launch'
5
4
 
6
5
  describe Chef::Knife::ClusterLaunch do
7
6
  let(:cluster) do
@@ -29,7 +28,7 @@ describe Chef::Knife::ClusterLaunch do
29
28
  subject.config[:bootstrap] = true
30
29
  end
31
30
  context 'full slice' do
32
- let(:slice){ ['gunbai'] }
31
+ let(:slice){ ['samurai-gunbai'] }
33
32
  it 'fails if there are multiple environments' do
34
33
  expect{ subject.run }.to raise_error("Cannot bootstrap multiple chef environments")
35
34
  end
@@ -0,0 +1,26 @@
1
+ Ironfan.realm 'samurai' do
2
+ cluster 'gunbai' do
3
+ cloud(:ec2) do
4
+ permanent false
5
+ availability_zones ['us-east-1d']
6
+ flavor 't1.micro'
7
+ backing 'ebs'
8
+ image_name 'natty'
9
+ bootstrap_distro 'ubuntu10.04-ironfan'
10
+ chef_client_script 'client.rb'
11
+ mount_ephemerals
12
+ end
13
+
14
+ environment :dev
15
+
16
+ role :ssh
17
+ cloud(:ec2).security_group(:ssh).authorize_port_range(22..22)
18
+
19
+ facet :hub do
20
+ end
21
+
22
+ facet :spoke do
23
+ environment :other
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEAti1Hi8y9u0pSbaYTPZOSH/Q55J8cncUnOKvRRihSFjcKv9PP
3
+ G4KAaZNySNVZxN9QQnBGReLuq671ZqLqkugy1FtDeC/HjdYdNW1hyI6or9oPYZ1r
4
+ zak1ws/DpE8IyRYABmtpQ4qi2B8coQymjRFInL80ctk48cRkm3Y2cxr9+y3nyrJY
5
+ x7JSMIyNgmL/5SVF/MZ+scbFESdK/bBfTYh2wxTYAXnebsXbuGJEHqxPjzIttmFC
6
+ x8FHJx+F5MJVqdVncYI3w/ktN/02K8ejvIR+BcKqarIQxagDCig3R56Yicd4PfPP
7
+ lWYCsojxS5mq5PmwEg2rYTJUblV7UYub74OO0wIDAQABAoIBAFIz9Ei8xhAw5Sjc
8
+ +2mZoSISDd1/fmYihCQqQ3Ao2YF0rMEKTjXXmSIKilMbEjqnmYuhJdR7Jb8KX2lE
9
+ shw/8k+oLrWYua7ioqNtC+Z3mN5gwvgFFJPkeoHBRkJp90jlSHWdGg6EDB8BSuXQ
10
+ 04Zr+hvgm0YHho5xVARiPweJcnlX5fI3RlwcTaC0gIpx2cgh/PdxkV6ivCumd2FZ
11
+ nAb2EK4VTtkZx7AkFZX0Qs04wuI6DVOxKCH0wNq3060E467bRde37P3XEgnwVoLz
12
+ vQMiD+so4jhs14wpRDNX6YdW0pimWOASUwDL39BT8xzZc4Xhbw62DuqU2EpaTxJm
13
+ FiM9tOECgYEA6cPy0z9nBPT70oTGMAsGV+kZ9M+kaIkgTtu831BRzO7DvScC7HS0
14
+ LT0pdYaLVcikDtLgDeVIV83av8l41R4jR4roei1DMp+f5yQWOnLeDqG+uqyOHP9v
15
+ pyYApmx/dfuTZ0d7xjU5CMle24xCrxNhUnZ0K3h+csPFw6ZgNFUNzfUCgYEAx4Eu
16
+ DBCiM4fL3Pge56iSMeZBbd44be2iv0JjcDGwwzW9sC4nS6UhUXRiY05OnRZCXCEe
17
+ sXtGdWVQJUFWclnFrtnpYJlXjRhB4UR6qm53jtJdpN34mVqFpOFiJdRMB6eTunoy
18
+ wVvAy4sDwd+A8uQCNp28od91j+ImgdoCpMdE5KcCgYEA09mp+bpO4ZYnlZyQg7+q
19
+ CweMZ2m6ZKZJKk5Ht9XxnBiSOZzeMG5/TzRLm1/IbIC99VU0ikNNMY20ffTXVcTP
20
+ UinYD8lvSbSR1IbGwkeRaI8667AvxqXTiRaOpkRTqxfIeWO2D2Xyfz0Hg050rHeS
21
+ zondM/wqFFXJp0rjium97fUCgYBnyx1ZyY2ZoZy+aZgqjdkBfPmtX1+cUXXKa4+w
22
+ XynHZb46Wsi24kJjTlmhsKvVri74H4MIc0pE6WC5ATUoaOwf+98fEqgqD+S2fhoT
23
+ cUViWK+/hnw/zIibL2cQp1Km6NhCvDCLyGCVhM1/n/hGZbmBEK+Cx+8x3EaMaA/Y
24
+ CpQdIQKBgQCVUB4/mV46FenaTfbDD1dEGRgyXKmkTmJyUmwPvHEJgA5fb5cDi28l
25
+ NMkqnZDx2SdPsxJM/JFrViPX6FsK+1cpg5b+IBTPYVYchtXgbm4NytCIr67VxIwi
26
+ TncqU0OTD5vYpKeFcaidsAI89Xmc69t5rQp2xsuaaJJeCXi/l1D0+Q==
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEowIBAAKCAQEAusYm0m90VKacujHjuzyYXUsRYvth9cN4C4rWBD3u/SBN0eGY
3
+ bWJG2AmxlYEP8IbaMIALiLa5zOhL+hBsFWz1LQdMt3eJrMu+qua0is1kXTtOTFxG
4
+ gj/Nkw9JkUXrOUjN3FmJYppBPJiDG3lyy3ero4dcHaBDJ6VfbeiH7DKHSH8xRV18
5
+ EIGjkQL2+o/koz7MMtfQx92Q9W+o+wJPiwqkT9LokO/RQGS0oJ5xqTnZtKJbBYlL
6
+ Oo4K2ggvGuKcmfTpnsclZCxdZtJtOrMmHKQ+S4CxwY/piRD9bnxDQVkTwcEIaYwJ
7
+ PD91vEQKZvkht71pqsQMiwIG6ha992XaCDE9RwIDAQABAoIBAFQ523P2Uu2BnRfS
8
+ O7JJ5yPbIGIUnt5nYZFC8LRFAasgkDdflo9tTClMZcrXwspi5a4NcCYc0Lj44JpK
9
+ IZOf6Qh/TDdILsu/raIAG9akPOhWQD7rNdiy0Q/KSxC6CRNyI3OE5RGUImsjE6ym
10
+ HgBnXP2HoyCxDteoGdrEi9cWCi/EdljUHlygLcGuDAogJ6ttu8gslmbRP2pkTjul
11
+ 3aDjJB1788zaKQ+d95y4mT97Gc2LrOCdp3s9z1XCYqQvxMYo1Dh3D9xCZwCC7Xr7
12
+ VEWPY7t0uTMM3n8afAT2735p9KUz9hgv5Q8fY0diX4PmgT5rDcPlQhJNd9kcikU9
13
+ hoEfSYECgYEA6c7dd159ggMwRWDWUbneFl8vD+UUI5gsecNcd6Fde7BW7/uGzPyL
14
+ 1g0V2qFdnpOuKpJ+WCnclmE4mXvi2oFeMoJ00SsQCp6MvMyDF732VVczOpBmBjIY
15
+ RTuepXPgZTkTlebZBKBR70lA1Vf1Z+gu7c3XTjxwXXnMcI6aKnCqBSECgYEAzIBw
16
+ rRSRpjlegKzmsBtG1a/UWoFBJyKSBYS0gYcYTOCNrr2nnB0eXRJhMeiWSC+CvyEP
17
+ WVby8+4QSXV4JzfYVgyUgTPgXuJPppLfl3Ldb7q68vDfcyX4XQI+41AirNfpyyyz
18
+ sz7pBHV+LyGjTn8eHgtK+FjLVTh33tSs4ro2jWcCgYAHL2JC7tZwjmSHXUh4znty
19
+ uI4bsPCDf4OuYkCPNJhI2sxxJ4um9QPfGhvX0imsW+F4UXQshWzP+kDhBpucF2mr
20
+ p7KrUuV1ThYJH0fQDPhq+vkKDbH08skoJ4LilsMImU5uxt9YcwzRi7DAXame/dWj
21
+ XTYGo3jYhouv0dIPB9NRwQKBgQDLpMOPt8Hqk4qF/KekiyUYugVvMvOccxKSKDpQ
22
+ GiWauKqebgIwtdZ8vEbJmmG89ILwrY1JXAqH2nOhkzbZZwUpe1GO8AfotNi4ed3q
23
+ RNo53us37aG2WwNeK1RQrIY7NK9+Qb+ZKXaFmDLV4FttWay2Imy/rjydWqQT5Bld
24
+ li2o1QKBgET6ytLgQ9ZDVW7e2e1NecKzsQHEjY8RYQTpEDM/swG+IycIEO+zjNtH
25
+ cWu7TqdkrByxr/KX6hU5HNhRooQJtuqwlyxaGBUBGl6W6fTw2NJBuqAku37Amx2z
26
+ 4yAPq7VZfxUpXYmYaKp4msI1FPoLH7rD5z8NzgyxGNh9Ko9GBNCA
27
+ -----END RSA PRIVATE KEY-----
File without changes
@@ -1,7 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'ironfan'
4
-
5
3
  describe Ironfan::Dsl::Cluster do
6
4
  subject do
7
5
  Ironfan.cluster 'foo' do
@@ -12,6 +10,7 @@ describe Ironfan::Dsl::Cluster do
12
10
  role :is_last, :last
13
11
  role :is_first, :first
14
12
  end
13
+ Ironfan.cluster('foo').resolve
15
14
  end
16
15
 
17
16
  its(:environment) { should eql :dev }
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'gorillib/diff'
3
- require_relative '../spec_helper/dummy_diff_drawer.rb'
4
2
 
5
3
  describe Gorillib::DiffFormatter do
6
4
  it 'writes the indices of displayed elements for both sides' do
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'ironfan'
3
2
 
4
3
  describe Ironfan::Dsl do
5
4
  context 'when joining requirement pairs' do
@@ -58,17 +57,21 @@ describe Ironfan::Dsl do
58
57
 
59
58
  context 'when aggregating requirements' do
60
59
  before(:each) do
61
- Ironfan::Dsl.class_eval{ @@testing = true }
62
-
63
60
  Ironfan::Dsl::Component.template(%w[foo]) do
61
+ require_strict_versioning false
62
+
64
63
  cookbook_req 'a', '>= 1.2.3'
65
64
  def project(*_) end
66
65
  end
67
66
  Ironfan::Dsl::Component.template(%w[bar]) do
67
+ require_strict_versioning false
68
+
68
69
  cookbook_req 'a', '>= 1.2.5'
69
70
  def project(*_) end
70
71
  end
71
72
  Ironfan::Dsl::Component.template(%w[baz]) do
73
+ require_strict_versioning false
74
+
72
75
  cookbook_req 'a', '>= 1.2.7'
73
76
  def project(*_) end
74
77
  end
@@ -1,13 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'ironfan'
4
-
5
3
  describe Ironfan::Dsl::Cluster do
6
- let (:cluster) do
7
- Ironfan.cluster "sparky" do
4
+ let(:cluster) do
5
+ Ironfan.cluster 'sparky' do
8
6
 
9
7
  cloud(:ec2) do
10
- security_group(:ssh).authorize_port_range 22..22
8
+ security_group(:ssh).authorize_port_range(22..22)
11
9
  flavor 't1.micro'
12
10
  end
13
11
 
@@ -15,28 +13,29 @@ describe Ironfan::Dsl::Cluster do
15
13
  instances 3
16
14
  cloud(:ec2) do
17
15
  flavor 'm1.small'
18
- mount_ephemerals({ :disks => { 0 => { :mount_point => '/data' } } })
16
+ mount_ephemerals(disks: { 0 => { mount_point: '/data' } })
19
17
  end
20
- end
21
-
18
+ end
22
19
  end
20
+
21
+ Ironfan.cluster('sparky').resolve
23
22
  end
24
23
 
25
- describe 'web facet server resolution' do
26
- before { @facet = cluster.facets.values.first }
27
- subject { @facet }
28
- its(:name) { should eql "web" }
24
+ context 'web facet server resolution' do
25
+ subject(:facet){ cluster.facets.values.first }
26
+
27
+ its(:name){ should eq('web') }
29
28
 
30
- it 'should have the right number of servers' do
31
- @facet.servers.length.should == 3
29
+ it 'has the right number of servers' do
30
+ facet.servers.length.should eq(3)
32
31
  end
33
32
 
34
- it 'should have one cloud provider, EC2' do
35
- @facet.servers[0].clouds.keys.should == [ :ec2 ]
33
+ it 'has one cloud provider, EC2' do
34
+ facet.servers[0].clouds.keys.should eq([:ec2])
36
35
  end
37
36
 
38
- it 'should have its first ephemeral disk mounted at /data' do
39
- @facet.servers[0].implied_volumes[1].mount_point.should == '/data'
37
+ it 'has its first ephemeral disk mounted at /data' do
38
+ facet.servers[0].implied_volumes[1].mount_point.should eq('/data')
40
39
  end
41
40
  end
42
41