foreplay 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -103,8 +103,12 @@ end
103
103
 
104
104
  ## Contributing
105
105
 
106
- 1. Fork it
107
- 2. Create your feature branch (`git checkout -b my-new-feature`)
108
- 3. Commit your changes (`git commit -am 'Add some feature'`)
109
- 4. Push to the branch (`git push origin my-new-feature`)
110
- 5. Create new Pull Request
106
+ 1. Fork it
107
+ 1. Create your feature branch (`git checkout -b my-new-feature`)
108
+ 1. Commit your changes (`git commit -am 'Add some feature'`)
109
+ 1. Push to the branch (`git push origin my-new-feature`)
110
+ 1. Create new Pull Request
111
+
112
+ ## Acknowledgements
113
+
114
+ 1. Thanks to Ryan Bigg for the guide to making your first gem https://github.com/radar/guides/blob/master/gem-development.md
@@ -91,6 +91,6 @@ Feature: deploy
91
91
  Scenario: deploy
92
92
  When I run `foreplay setup -r git@github.com:Xenapto/foreplay.git -s web.example.com --password "top-secret"`
93
93
  And I run `foreplay deploy production`
94
- Then the output should contain "Deploying aruba to web.example.com in the web role on the production environment"
94
+ Then the output should contain "Deploying aruba to web.example.com for the web role in the production environment"
95
95
  And the output should contain "Connecting to web.example.com"
96
96
  And the output should contain "There was a problem starting an ssh session on web.example.com"
@@ -1,6 +1,7 @@
1
1
  require 'thor/group'
2
2
  require 'yaml'
3
3
  require 'net/ssh'
4
+ require 'net/ssh/shell'
4
5
  require 'active_support/inflector'
5
6
  require 'active_support/core_ext/object'
6
7
  require 'active_support/core_ext/hash'
@@ -15,7 +16,8 @@ module Foreplay
15
16
  argument :environment, :type => :string, :required => true
16
17
  argument :filters, :type => :hash, :required => false
17
18
 
18
- DEFAULTS_KEY = 'defaults'
19
+ DEFAULTS_KEY = 'defaults'
20
+ INDENT = ' ' * 4
19
21
 
20
22
  def parse
21
23
  # Explain what we're going to do
@@ -73,7 +75,7 @@ module Foreplay
73
75
  servers = instructions[:servers]
74
76
  preposition = mode == :deploy ? 'to' : 'for'
75
77
 
76
- puts "#{mode.capitalize}ing #{instructions[:name].yellow} #{preposition} #{servers.join(', ').yellow} in the #{instructions[:role].dup.yellow} role on the #{environment.dup.yellow} environment..." if servers.length > 1
78
+ puts "#{mode.capitalize}ing #{instructions[:name].yellow} #{preposition} #{servers.join(', ').yellow} for the #{instructions[:role].dup.yellow} role in the #{environment.dup.yellow} environment..." if servers.length > 1
77
79
  servers.each { |server| deploy_to_server server, instructions }
78
80
  end
79
81
 
@@ -88,7 +90,7 @@ module Foreplay
88
90
 
89
91
  instructions[:server] = server
90
92
 
91
- puts "#{mode.capitalize}ing #{name.yellow} #{preposition} #{server.yellow} in the #{role.dup.yellow} role on the #{environment.dup.yellow} environment"
93
+ puts "#{mode.capitalize}ing #{name.yellow} #{preposition} #{server.yellow} for the #{role.dup.yellow} role in the #{environment.dup.yellow} environment"
92
94
 
93
95
  # Substitute variables in the path
94
96
  path.gsub! '%u', user
@@ -98,7 +100,7 @@ module Foreplay
98
100
  steps = [ { :command => 'mkdir -p .foreplay && touch .foreplay/current_port && cat .foreplay/current_port', :silent => true } ]
99
101
 
100
102
  current_port_string = execute_on_server(steps, instructions).strip!
101
- puts current_port_string.blank? ? ' No instance is currently deployed' : " Current instance is using port #{current_port_string}"
103
+ puts current_port_string.blank? ? "#{INDENT}No instance is currently deployed" : "#{INDENT}Current instance is using port #{current_port_string}"
102
104
 
103
105
  current_port = current_port_string.to_i
104
106
 
@@ -129,6 +131,8 @@ module Foreplay
129
131
  :commentary => 'Trusting the .rvmrc file for the new instance' },
130
132
  { :command => "cd #{current_port}",
131
133
  :commentary => 'Configuring the new instance' },
134
+ { :command => 'mkdir -p config',
135
+ :commentary => "Making sure the config directory exists" },
132
136
  { :key => :env,
133
137
  :delimiter => '=',
134
138
  :prefix => '.',
@@ -144,29 +148,31 @@ module Foreplay
144
148
  :before => ' ',
145
149
  :header => "#{environment}:",
146
150
  :path => 'config/' },
147
- { :command => "bundle install",
151
+ { :command => 'bundle install',
148
152
  :commentary => 'Using bundler to install the required gems' },
149
- { :command => "sudo ln -f `which foreman` /usr/bin/foreman",
153
+ { :command => 'sudo ln -f `which foreman` /usr/bin/foreman',
150
154
  :commentary => 'Setting the current version of foreman to be the default' },
151
- { :command => "sudo foreman export upstart /etc/init",
155
+ { :command => 'sudo foreman export upstart /etc/init',
152
156
  :commentary => "Converting #{current_service} to an upstart service" },
153
157
  { :command => "sudo start #{current_service} || sudo restart #{current_service}",
154
158
  :commentary => 'Starting the service',
155
159
  :ignore_error => true },
156
160
  { :command => 'sleep 60',
157
161
  :commentary => 'Waiting 60s to give service time to start' },
158
- { :command => "sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{current_port.to_i + 100}",
162
+ { :command => "sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{current_port}",
159
163
  :commentary => "Adding firewall rule to direct incoming traffic on port 80 to port #{current_port}" },
160
- { :command => "sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{former_port.to_i + 100}",
161
- :commentary => "Removing previous firewall directing traffic to port #{former_port}",
164
+ { :command => "sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{former_port}",
165
+ :commentary => "Removing previous firewall rule directing traffic to port #{former_port}",
162
166
  :ignore_error => true },
163
- { :command => "sudo iptables-save > /etc/iptables/rules.v4",
164
- :commentary => "Saving iptables rules to /etc/iptables/rules.v4" },
165
- { :command => "sudo iptables-save > /etc/iptables.up.rules",
166
- :commentary => "Saving iptables rules to /etc/iptables.up.rules" },
167
- { :command => "sudo iptables-save -c | egrep REDIRECT --color=never",
167
+ { :command => 'sudo iptables-save > /etc/iptables/rules.v4',
168
+ :commentary => 'Attempting to save firewall rules to /etc/iptables/rules.v4',
169
+ :ignore_error => true },
170
+ { :command => 'sudo iptables-save > /etc/iptables.up.rules',
171
+ :commentary => 'Attempting to save firewall rules to /etc/iptables.up.rules',
172
+ :ignore_error => true },
173
+ { :command => 'sudo iptables-save -c | egrep REDIRECT --color=never',
168
174
  :ignore_error => true,
169
- :commentary => "Current firewall NAT configuration:" },
175
+ :commentary => 'Current firewall NAT configuration:' },
170
176
  { :command => "sudo stop #{former_service} || echo 'No previous instance running'",
171
177
  :commentary => 'Stopping the previous instance',
172
178
  :ignore_error => true },
@@ -192,10 +198,10 @@ module Foreplay
192
198
  if private_key.blank?
193
199
  terminate('No authentication methods supplied. You must supply a private key, key file or password in the configuration file') if keyfile.blank?
194
200
  # Get the key from the key file
195
- puts " Using private key from #{keyfile}"
201
+ puts "#{INDENT}Using private key from #{keyfile}"
196
202
  private_key = File.read keyfile
197
203
  else
198
- puts " Using private key from the configuration file"
204
+ puts "#{INDENT}Using private key from the configuration file"
199
205
  end
200
206
 
201
207
  options[:key_data] = [private_key]
@@ -208,12 +214,12 @@ module Foreplay
208
214
  output = ''
209
215
 
210
216
  if mode == :deploy
211
- puts " Connecting to #{server}"
217
+ puts "#{INDENT}Connecting to #{server}"
212
218
 
213
219
  # SSH connection
214
220
  begin
215
221
  Net::SSH.start(server, user, options) do |session|
216
- puts " Successfully connected to #{server}"
222
+ puts "#{INDENT}Successfully connected to #{server}"
217
223
 
218
224
  session.shell do |sh|
219
225
  steps.each do |step|
@@ -234,7 +240,7 @@ module Foreplay
234
240
  sh.wait!
235
241
 
236
242
  if step[:ignore_error] == true || process.exit_status == 0
237
- print output.gsub!(/^/, " ") unless step[:silent] == true
243
+ print output.gsub!(/^/, INDENT * 2) unless step[:silent] == true || output.blank?
238
244
  else
239
245
  terminate(output)
240
246
  end
@@ -250,7 +256,7 @@ module Foreplay
250
256
  steps.each do |step|
251
257
  commands = build_commands step, instructions
252
258
 
253
- commands.each { |command| puts " #{command}" unless step[:silent] }
259
+ commands.each { |command| puts "#{INDENT * 2}#{command}" unless step[:silent] }
254
260
  end
255
261
  end
256
262
 
@@ -258,7 +264,7 @@ module Foreplay
258
264
  end
259
265
 
260
266
  def build_commands step, instructions
261
- puts " #{(step[:commentary] || step[:command]).yellow}" unless step[:silent] == true
267
+ puts "#{INDENT}#{(step[:commentary] || step[:command]).yellow}" unless step[:silent] == true
262
268
 
263
269
  # Each step can be (1) a command or (2) a series of values to add to a file
264
270
  if step.has_key? :key
@@ -1,3 +1,3 @@
1
1
  module Foreplay
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -54,50 +54,10 @@ describe Foreplay::Deploy do
54
54
  expect { Foreplay::Deploy.start([:deploy, 'production', '']) }.to raise_error(RuntimeError, /.*There was a problem starting an ssh session on web.example.com*/)
55
55
  end
56
56
 
57
- it "should check the config" do
58
- output = <<OUTPUT
59
- Checking \e[0;33;49mproduction\e[0m environment, all roles, all servers
60
- Checking \e[0;33;49mforeplay\e[0m for \e[0;33;49mweb.example.com\e[0m in the \e[0;33;49mweb\e[0m role on the \e[0;33;49mproduction\e[0m environment
61
- No instance is currently deployed
62
- \e[0;33;49mSetting the port for the new instance to 50000\e[0m
63
- echo 50000 > .foreplay/current_port
64
- \e[0;33;49mCloning repository git@github.com:Xenapto/foreplay.git\e[0m
65
- mkdir -p apps/foreplay && cd apps/foreplay && rm -rf 50000 && git clone git@github.com:Xenapto/foreplay.git 50000
66
- \e[0;33;49mTrusting the .rvmrc file for the new instance\e[0m
67
- rvm rvmrc trust 50000
68
- \e[0;33;49mConfiguring the new instance\e[0m
69
- cd 50000
70
- \e[0;33;49mBuilding .env\e[0m
71
- \e[0;33;49mBuilding .foreman\e[0m
72
- \e[0;33;49mBuilding config/database.yml\e[0m
73
- \e[0;33;49mUsing bundler to install the required gems\e[0m
74
- bundle install
75
- \e[0;33;49mSetting the current version of foreman to be the default\e[0m
76
- sudo ln -f `which foreman` /usr/bin/foreman
77
- \e[0;33;49mConverting foreplay-50000 to an upstart service\e[0m
78
- sudo foreman export upstart /etc/init
79
- \e[0;33;49mStarting the service\e[0m
80
- sudo start foreplay-50000 || sudo restart foreplay-50000
81
- \e[0;33;49mWaiting 60s to give service time to start\e[0m
82
- sleep 60
83
- \e[0;33;49mAdding firewall rule to direct incoming traffic on port 80 to port 50000\e[0m
84
- sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 50100
85
- \e[0;33;49mRemoving previous firewall directing traffic to port 51000\e[0m
86
- sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 51100
87
- \e[0;33;49mSaving iptables rules to /etc/iptables/rules.v4\e[0m
88
- sudo iptables-save > /etc/iptables/rules.v4
89
- \e[0;33;49mSaving iptables rules to /etc/iptables.up.rules\e[0m
90
- sudo iptables-save > /etc/iptables.up.rules
91
- \e[0;33;49mCurrent firewall NAT configuration:\e[0m
92
- sudo iptables-save -c | egrep REDIRECT --color=never
93
- \e[0;33;49mStopping the previous instance\e[0m
94
- sudo stop foreplay-51000 || echo 'No previous instance running'
95
- Deployment configuration check was successful
96
- OUTPUT
97
-
98
- output.split("\n").reverse.each { |line| $stdout.should_receive(:puts).with(line) }
99
- Foreplay::Deploy.start [:check, 'production', '']
100
- end
57
+ it "should check the config" do
58
+ $stdout.should_receive(:puts).at_least(:once)
59
+ Foreplay::Deploy.start [:check, 'production', '']
60
+ end
101
61
 
102
62
  it "should deploy to the environment" do
103
63
  Net::SSH.should_receive(:start).with('web.example.com', 'fred', { :verbose => :warn, :password => 'trollope' }).and_yield(session)
@@ -126,8 +86,8 @@ OUTPUT
126
86
  'sudo foreman export upstart /etc/init',
127
87
  'sudo start foreplay-50000 || sudo restart foreplay-50000',
128
88
  'sleep 60',
129
- 'sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 50100',
130
- 'sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 51100',
89
+ 'sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 50000',
90
+ 'sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 51000',
131
91
  'sudo iptables-save > /etc/iptables/rules.v4',
132
92
  'sudo iptables-save > /etc/iptables.up.rules',
133
93
  'sudo iptables-save -c | egrep REDIRECT --color=never',
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreplay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-09 00:00:00.000000000 Z
12
+ date: 2013-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -224,7 +224,6 @@ files:
224
224
  - features/support/env.rb
225
225
  - foreplay.gemspec
226
226
  - foreplay.rake
227
- - foreplay.rb
228
227
  - lib/foreplay.rb
229
228
  - lib/foreplay/cli.rb
230
229
  - lib/foreplay/deploy.rb
@@ -251,7 +250,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
251
250
  version: '0'
252
251
  segments:
253
252
  - 0
254
- hash: -981112274767649738
253
+ hash: -3290811328696495946
255
254
  required_rubygems_version: !ruby/object:Gem::Requirement
256
255
  none: false
257
256
  requirements:
@@ -260,7 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
260
259
  version: '0'
261
260
  segments:
262
261
  - 0
263
- hash: -981112274767649738
262
+ hash: -3290811328696495946
264
263
  requirements: []
265
264
  rubyforge_project:
266
265
  rubygems_version: 1.8.25
data/foreplay.rb DELETED
@@ -1,246 +0,0 @@
1
- # encoding: utf-8
2
- require 'yaml'
3
- require 'net/ssh'
4
-
5
- class Foreplay
6
- class << self
7
- def push check_only = false
8
- environment = ENV['ENV']
9
- config_file = "#{Rails.root}/config/foreplay.yml"
10
- config_all = YAML.load(File.read(config_file))
11
-
12
- # This environment
13
- raise RuntimeError, "No deployment environment defined. Set the ENV environment variable." if environment.blank?
14
- raise RuntimeError, "No deployment configuration defined for #{environment} environment. Check #{config_file}" unless config_all.has_key? environment
15
- config = config_all[environment]
16
-
17
- # Establish defaults
18
- # First the default defaults
19
- defaults = {
20
- 'name' => Rails.application.class.parent_name.underscore,
21
- 'environment' => environment,
22
- 'env' => { 'RAILS_ENV' => environment }
23
- }
24
-
25
- defaults = deep_merge_with_arrays(defaults, config_all['defaults']) if config_all.has_key? 'defaults' # Then the global defaults
26
- defaults = deep_merge_with_arrays(defaults, config['defaults']) if config.has_key? 'defaults' # Then the defaults for this environment
27
-
28
- config.each do |role, additional_instructions|
29
- next if role == 'defaults' # 'defaults' is not a role
30
- next unless ENV['ROLE'].blank? || ENV['ROLE'] == role # Only deploy to the role we've specified (or all roles if none is specified)
31
-
32
- instructions = deep_merge_with_arrays(defaults, additional_instructions).symbolize_keys
33
- instructions[:role] = role
34
- required_keys = [:name, :environment, :role, :servers, :path, :repository]
35
-
36
- required_keys.each { |key| raise RuntimeError, "Required key #{key} not found in instructions for #{environment} environment. Check #{config_file}" unless instructions.has_key? key }
37
-
38
- deploy_role instructions unless check_only
39
- end
40
-
41
- puts check_only ? 'Deployment configuration check was successful' : 'Finished deployment'
42
- end
43
-
44
- def deploy_role instructions
45
- servers = instructions[:servers]
46
- puts "Deploying #{instructions[:name]} to #{servers.join(', ')} for the #{instructions[:role]} role in the #{instructions[:environment]} environment..." if servers.length > 1
47
- servers.each { |server| deploy_to_server server, instructions }
48
- end
49
-
50
- def deploy_to_server server, instructions
51
- name = instructions[:name]
52
- environment = instructions[:environment]
53
- role = instructions[:role]
54
- path = instructions[:path]
55
- repository = instructions[:repository]
56
- user = instructions[:user]
57
-
58
- instructions[:server] = server
59
-
60
- puts "Deploying #{name} to #{server} for the #{role} role in the #{environment} environment"
61
-
62
- # Substitute variables in the path
63
- path.sub! '%u', user
64
- path.sub! '%a', name
65
-
66
- # Find out which port we're currently running on
67
- steps = [ { :command => 'mkdir -p .foreplay && touch .foreplay/current_port && cat .foreplay/current_port', :silent => true } ]
68
-
69
- current_port = execute_on_server(steps, instructions).strip!
70
- puts "Current instance is using port #{current_port}"
71
-
72
- # Switch ports
73
- if current_port == '50000'
74
- current_port = '51000'
75
- former_port = '50000'
76
- else
77
- current_port = '50000'
78
- former_port = '51000'
79
- end
80
-
81
- # Contents of .foreman file
82
- current_service = '%s-%s' % [name, current_port]
83
- former_service = '%s-%s' % [name, former_port]
84
-
85
- instructions[:foreman]['app'] = current_service
86
- instructions[:foreman]['port'] = current_port
87
- instructions[:foreman]['user'] = user
88
-
89
- # Commands to execute on remote server
90
- steps = [
91
- { :command => "echo #{current_port} > .foreplay/current_port" },
92
- { :command => "mkdir -p #{path} && cd #{path} && rm -rf #{current_port} && git clone #{repository} #{current_port}",
93
- :commentary => "Cloning repository #{repository}" },
94
- { :command => "rvm rvmrc trust #{current_port}" },
95
- { :command => "cd #{current_port}" },
96
- { :key => :env,
97
- :delimiter => '=',
98
- :prefix => '.',
99
- :commentary => 'Building .env' },
100
- { :key => :foreman,
101
- :delimiter => ': ',
102
- :prefix => '.',
103
- :commentary => 'Building .foreman' },
104
- { :key => :database,
105
- :delimiter => ': ',
106
- :suffix => '.yml',
107
- :commentary => 'Building config/database.yml',
108
- :before => ' ',
109
- :header => "#{environment}:",
110
- :path => 'config/' },
111
- { :command => "bundle install" },
112
- { :command => "sudo ln -f `which foreman` /usr/bin/foreman" },
113
- { :command => "sudo foreman export upstart /etc/init" },
114
- { :command => "sudo start #{current_service} || sudo restart #{current_service}",
115
- :ignore_error => true },
116
- { :command => 'sleep 60',
117
- :commentary => 'Waiting 60s to give service time to start' },
118
- { :command => "sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{current_port.to_i + 100}",
119
- :commentary => "Adding firewall rule to direct incoming traffic on port 80 to port #{current_port}" },
120
- { :command => "sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{former_port.to_i + 100}",
121
- :commentary => "Removing previous firewall directing traffic to port #{former_port}",
122
- :ignore_error => true },
123
- { :command => "sudo iptables -t nat -L | grep REDIRECT",
124
- :ignore_error => true,
125
- :commentary => "Current firewall NAT configuration:" },
126
- { :command => "sudo stop #{former_service} || echo 'No previous instance running'",
127
- :ignore_error => true },
128
- ]
129
-
130
- execute_on_server steps, instructions
131
- end
132
-
133
- def execute_on_server steps, instructions
134
- server = instructions[:server]
135
- user = instructions[:user]
136
- password = instructions[:password]
137
- keyfile = instructions[:keyfile]
138
- key = instructions[:key]
139
-
140
- keyfile.sub! '~' , ENV['HOME'] # Remote shell won't expand this for us
141
-
142
- # SSH authentication methods
143
- options = { :verbose => :warn }
144
-
145
- if password.blank?
146
- # If there's no password we must supply a private key
147
- if key.blank?
148
- raise RuntimeError, "No authentication methods supplied. You must supply a private key, key file or password in the configuration file" if keyfile.blank?
149
- # Get the key from the key file
150
- puts "Using private key from #{keyfile}"
151
- key = File.read keyfile
152
- else
153
- puts "Using private key from the configuration file"
154
- end
155
-
156
- options[:key_data] = [key]
157
- else
158
- # Use the password supplied
159
- options[:password] = password
160
- end
161
-
162
- # Capture output of last command to return to the calling routine
163
- output = ''
164
-
165
- # SSH connection
166
- Net::SSH.start(server, user, options) do |ssh|
167
- puts "Successfully connected to #{server}"
168
-
169
- ssh.shell do |sh|
170
- steps.each do |step|
171
- # Output from this step
172
- output = ''
173
- previous = '' # We don't need or want the final CRLF
174
-
175
- puts step[:commentary] || step[:command] unless step[:silent] == true
176
-
177
- # Each step can be (1) a command or (2) a series of values to add to a file
178
- if step.has_key? :key
179
- step[:silent] = true
180
-
181
- # Add values from the config file to a file on the remote machine
182
- key = step[:key]
183
- prefix = step[:prefix] || ''
184
- suffix = step[:suffix] || ''
185
- path = step[:path] || ''
186
- before = step[:before] || ''
187
- delimiter = step[:delimiter] || ''
188
- after = step[:after] || ''
189
-
190
- filename = '%s%s%s%s' % [path, prefix, key, suffix]
191
- commands = step.has_key?(:header) ? ['echo "%s" >> %s' % [step[:header], filename]] : []
192
-
193
- instructions[key].each { |k, v| commands << 'echo "%s%s%s%s%s" >> %s' % [before, k, delimiter, v, after, filename] }
194
- else
195
- # ...or just execute the command specified
196
- commands = [step[:command]]
197
- end
198
-
199
- commands.each do |command|
200
- process = sh.execute command
201
-
202
- process.on_output do |p, o|
203
- previous = o
204
- output += previous
205
- end
206
-
207
- sh.wait!
208
-
209
- if step[:ignore_error] == true || process.exit_status == 0
210
- print "#{output}" unless step[:silent] == true
211
- else
212
- raise RuntimeError, output
213
- end
214
- end
215
- end
216
- end
217
- end
218
-
219
- output
220
- end
221
-
222
- # Returns a new hash with +hash+ and +other_hash+ merged recursively, including arrays.
223
- #
224
- # h1 = { x: { y: [4,5,6] }, z: [7,8,9] }
225
- # h2 = { x: { y: [7,8,9] }, z: 'xyz' }
226
- # h1.deep_merge_with_arrays(h2)
227
- # #=> {:x=>{:y=>[4, 5, 6, 7, 8, 9]}, :z=>[7, 8, 9, "xyz"]}
228
- def deep_merge_with_arrays(hash, other_hash)
229
- new_hash = hash.deep_dup
230
-
231
- other_hash.each_pair do |k,v|
232
- tv = new_hash[k]
233
-
234
- if tv.is_a?(Hash) && v.is_a?(Hash)
235
- new_hash[k] = deep_merge_with_arrays(tv, v)
236
- elsif tv.is_a?(Array) || v.is_a?(Array)
237
- new_hash[k] = Array.wrap(tv) + Array.wrap(v)
238
- else
239
- new_hash[k] = v
240
- end
241
- end
242
-
243
- new_hash
244
- end
245
- end
246
- end