taste_tester 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +10 -4
- data/bin/taste-tester +36 -18
- data/lib/taste_tester/client.rb +5 -4
- data/lib/taste_tester/commands.rb +6 -5
- data/lib/taste_tester/config.rb +12 -6
- data/lib/taste_tester/hooks.rb +5 -3
- data/lib/taste_tester/host.rb +35 -23
- data/lib/taste_tester/logging.rb +3 -3
- data/lib/taste_tester/server.rb +11 -11
- data/lib/taste_tester/ssh.rb +9 -6
- data/lib/taste_tester/state.rb +7 -7
- data/lib/taste_tester/tunnel.rb +16 -13
- metadata +55 -13
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Taste Tester
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/facebook/taste-tester.svg)](http://travis-ci.org/facebook/taste-tester)
|
4
|
+
|
3
5
|
## Intro
|
4
6
|
Ohai!
|
5
7
|
|
@@ -38,8 +40,9 @@ See the help for futher information.
|
|
38
40
|
|
39
41
|
## Prerequisites
|
40
42
|
|
41
|
-
* Taste Tester assumes that /etc/chef/client.rb on your
|
42
|
-
that your real config is /etc/chef/client-prod.rb
|
43
|
+
* Taste Tester assumes that /etc/chef/client.rb and /etc/chef/client.pem on your
|
44
|
+
servers is a symlink and that your real config is /etc/chef/client-prod.rb and
|
45
|
+
/etc/chef/client-prod.pem, respectively.
|
43
46
|
|
44
47
|
* Taste Tester assumes that it's generally safe to "go back" to production. I.e.
|
45
48
|
We set things up so you can set a cronjob to un-taste-test a server after the
|
@@ -47,7 +50,10 @@ desired amount of time, which means it must be (relatively) safe to revert
|
|
47
50
|
back.
|
48
51
|
|
49
52
|
* Taste Tester assumes you use a setup similar to grocery-delivery in
|
50
|
-
production. Specifically that you don't use versions or environments.
|
53
|
+
production. Specifically that you don't use versions or environments.
|
54
|
+
|
55
|
+
* Taste Tester assumes you have password-less SSH authentication to the hosts
|
56
|
+
you want to test on, i.e. SSH public/private keys, SSH certificates, Kerberos
|
51
57
|
|
52
58
|
## Dependencies
|
53
59
|
|
@@ -79,7 +85,7 @@ standard Ruby.
|
|
79
85
|
All command-line options are available in the config file:
|
80
86
|
* debug (bool, default: `false`)
|
81
87
|
* timestamp (bool, default: `false`)
|
82
|
-
* config_file (string, default: `/etc/
|
88
|
+
* config_file (string, default: `/etc/taste-tester-config.rb`)
|
83
89
|
* plugin_path (string, default: `/etc/taste-tester-plugin.rb`)
|
84
90
|
* repo (string, default: `#{ENV['HOME']}/ops`)
|
85
91
|
* testing_time (int, default: `3600`)
|
data/bin/taste-tester
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
#!/
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
3
3
|
|
4
4
|
# Copyright 2013-present Facebook
|
5
|
-
#
|
5
|
+
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
8
8
|
# You may obtain a copy of the License at
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# Unless required by applicable law or agreed to in writing, software
|
13
13
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
14
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -18,10 +18,6 @@
|
|
18
18
|
$LOAD_PATH.unshift(File.dirname(File.realpath(__FILE__)) + '/../lib')
|
19
19
|
|
20
20
|
# rubocop:disable UnusedBlockArgument, AlignParameters
|
21
|
-
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm')
|
22
|
-
puts 'Please disable RVM before running taste-tester'
|
23
|
-
exit(1)
|
24
|
-
end
|
25
21
|
|
26
22
|
require 'rubygems'
|
27
23
|
require 'time'
|
@@ -43,6 +39,15 @@ end
|
|
43
39
|
# Command line parsing and param descriptions
|
44
40
|
module TasteTester
|
45
41
|
verify = 'Verify your changes were actually applied as intended!'.red
|
42
|
+
|
43
|
+
# Do an initial read of the config file if it's in the default place, so
|
44
|
+
# that if people override chef_client_command the help message is correct.
|
45
|
+
if File.exists?(File.expand_path(TasteTester::Config.config_file))
|
46
|
+
TasteTester::Config.from_file(
|
47
|
+
File.expand_path(TasteTester::Config.config_file)
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
46
51
|
cmd = TasteTester::Config.chef_client_command
|
47
52
|
description = <<-EOF
|
48
53
|
Welcome to taste-tester!
|
@@ -50,17 +55,17 @@ Welcome to taste-tester!
|
|
50
55
|
Usage: taste-tester <mode> [<options>]
|
51
56
|
|
52
57
|
TLDR; Most common usage is:
|
53
|
-
vi cookbooks/...
|
54
|
-
taste-tester test -s [host]
|
55
|
-
ssh root@[host]
|
56
|
-
#{format('%-28s', " #{cmd}")}
|
57
|
-
vi cookbooks/...
|
58
|
-
taste-tester upload
|
59
|
-
ssh root@[host]
|
60
|
-
#{format('%-28s', " #{cmd}")}
|
58
|
+
vi cookbooks/... # Make your changes and commit locally
|
59
|
+
taste-tester test -s [host] # Put host in test mode
|
60
|
+
ssh root@[host] # Log on host
|
61
|
+
#{format('%-28s', " #{cmd}")} # Run chef and watch it break
|
62
|
+
vi cookbooks/... # Fix your cookbooks
|
63
|
+
taste-tester upload # Upload the diff
|
64
|
+
ssh root@[host] # Log on host
|
65
|
+
#{format('%-28s', " #{cmd}")} # Run chef and watch it succeed
|
61
66
|
<#{verify}>
|
62
|
-
taste-tester untest [host]
|
63
|
-
|
67
|
+
taste-tester untest -s [host] # Put host back in production
|
68
|
+
# (optional - will revert itself after 1 hour)
|
64
69
|
|
65
70
|
And you're done! See the above wiki page for more details.
|
66
71
|
|
@@ -247,6 +252,13 @@ MODES:
|
|
247
252
|
options[:repo] = dir
|
248
253
|
end
|
249
254
|
|
255
|
+
opts.on(
|
256
|
+
'--repo-type TYPE',
|
257
|
+
'Override repo type, default is auto.'
|
258
|
+
) do |type|
|
259
|
+
options[:repo_type] = type
|
260
|
+
end
|
261
|
+
|
250
262
|
opts.on(
|
251
263
|
'-R', '--roles ROLE[,ROLE]', Array,
|
252
264
|
'Specific roles to upload. Intended mostly for debugging,' +
|
@@ -279,6 +291,12 @@ MODES:
|
|
279
291
|
options[:use_ssh_tunnels] = s
|
280
292
|
end
|
281
293
|
|
294
|
+
opts.on(
|
295
|
+
'-e', '--ssh CMD', 'SSH command to use, defaults to "ssh".'
|
296
|
+
) do |c|
|
297
|
+
options[:ssh_command] = c
|
298
|
+
end
|
299
|
+
|
282
300
|
opts.on('--skip-repo-checks', 'Skip repository sanity checks') do
|
283
301
|
options[:skip_repo_checks] = true
|
284
302
|
end
|
data/lib/taste_tester/client.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -30,6 +30,8 @@ module TasteTester
|
|
30
30
|
attr_accessor :force, :skip_checks
|
31
31
|
|
32
32
|
def initialize(server)
|
33
|
+
path = File.expand_path(TasteTester::Config.repo)
|
34
|
+
logger.warn("Using #{path}")
|
33
35
|
@server = server
|
34
36
|
@knife = BetweenMeals::Knife.new(
|
35
37
|
:logger => logger,
|
@@ -62,7 +64,6 @@ module TasteTester
|
|
62
64
|
def upload
|
63
65
|
checks unless @skip_checks
|
64
66
|
|
65
|
-
logger.warn("Using #{TasteTester::Config.repo}")
|
66
67
|
logger.info("Last commit: #{@repo.head_rev} " +
|
67
68
|
"'#{@repo.last_msg.split("\n").first}'" +
|
68
69
|
" by #{@repo.last_author[:email]}")
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -155,7 +155,7 @@ module TasteTester
|
|
155
155
|
server.start
|
156
156
|
end
|
157
157
|
client = TasteTester::Client.new(server)
|
158
|
-
client.skip_checks = true if TasteTester::Config.
|
158
|
+
client.skip_checks = true if TasteTester::Config.skip_repo_checks
|
159
159
|
client.force = true if TasteTester::Config.force_upload
|
160
160
|
client.upload
|
161
161
|
rescue => exception
|
@@ -174,8 +174,9 @@ module TasteTester
|
|
174
174
|
retry
|
175
175
|
end
|
176
176
|
end
|
177
|
-
logger.error(
|
177
|
+
logger.error('Upload failed')
|
178
178
|
logger.error(exception.to_s)
|
179
|
+
logger.error(exception.backtrace.join("\n"))
|
179
180
|
exit 1
|
180
181
|
end
|
181
182
|
end
|
data/lib/taste_tester/config.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -28,7 +28,7 @@ module TasteTester
|
|
28
28
|
extend BetweenMeals::Util
|
29
29
|
|
30
30
|
repo "#{ENV['HOME']}/ops"
|
31
|
-
repo_type '
|
31
|
+
repo_type 'auto'
|
32
32
|
base_dir 'chef'
|
33
33
|
cookbook_dirs ['cookbooks']
|
34
34
|
role_dir 'roles'
|
@@ -48,8 +48,10 @@ module TasteTester
|
|
48
48
|
tunnel_port 4001
|
49
49
|
timestamp_file '/etc/chef/test_timestamp'
|
50
50
|
use_ssh_tunnels false
|
51
|
+
ssh_command 'ssh'
|
51
52
|
use_ssl true
|
52
53
|
chef_zero_logging true
|
54
|
+
chef_config_path '/etc/chef'
|
53
55
|
|
54
56
|
skip_pre_upload_hook false
|
55
57
|
skip_post_upload_hook false
|
@@ -74,7 +76,7 @@ module TasteTester
|
|
74
76
|
end
|
75
77
|
|
76
78
|
def self.relative_role_dir
|
77
|
-
(base_dir && !base_dir.empty?) ? File.join(base_dir, role_dir) :
|
79
|
+
(base_dir && !base_dir.empty?) ? File.join(base_dir, role_dir) : role_dir
|
78
80
|
end
|
79
81
|
|
80
82
|
def self.databags
|
@@ -82,7 +84,11 @@ module TasteTester
|
|
82
84
|
end
|
83
85
|
|
84
86
|
def self.relative_databag_dir
|
85
|
-
|
87
|
+
if base_dir && !base_dir.empty?
|
88
|
+
File.join(base_dir, databag_dir)
|
89
|
+
else
|
90
|
+
databag_dir
|
91
|
+
end
|
86
92
|
end
|
87
93
|
|
88
94
|
def self.chef_port
|
data/lib/taste_tester/hooks.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -16,6 +16,8 @@
|
|
16
16
|
|
17
17
|
require 'taste_tester/logging'
|
18
18
|
require 'between_meals/util'
|
19
|
+
require 'between_meals/repo/hg'
|
20
|
+
require 'between_meals/repo/git'
|
19
21
|
|
20
22
|
module TasteTester
|
21
23
|
# Hooks placeholders
|
data/lib/taste_tester/host.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -39,8 +39,10 @@ module TasteTester
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def runchef
|
42
|
-
logger.warn("Running '#{TasteTester::Config.
|
43
|
-
|
42
|
+
logger.warn("Running '#{TasteTester::Config.chef_client_command}' " +
|
43
|
+
"on #{@name}")
|
44
|
+
cmd = "#{TasteTester::Config.ssh_command} " +
|
45
|
+
"#{TasteTester::Config.user}@#{@name} "
|
44
46
|
if TasteTester::Config.user != 'root'
|
45
47
|
cc = Base64.encode64(cmds).gsub(/\n/, '')
|
46
48
|
cmd += "\"echo '#{cc}' | base64 --decode | sudo bash -x\""
|
@@ -58,12 +60,12 @@ module TasteTester
|
|
58
60
|
io.close
|
59
61
|
$CHILD_STATUS.to_i
|
60
62
|
end
|
61
|
-
logger.warn("Finished #{TasteTester::Config.
|
63
|
+
logger.warn("Finished #{TasteTester::Config.chef_client_command}" +
|
62
64
|
" on #{@name} with status #{status}")
|
63
65
|
if status == 0
|
64
|
-
msg = "#{TasteTester::Config.
|
65
|
-
|
66
|
-
|
66
|
+
msg = "#{TasteTester::Config.chef_client_command} was successful" +
|
67
|
+
' - please log to the host and confirm all the intended' +
|
68
|
+
' changes were made'
|
67
69
|
logger.error msg.upcase
|
68
70
|
end
|
69
71
|
end
|
@@ -88,10 +90,11 @@ module TasteTester
|
|
88
90
|
ssh << "touch -t #{TasteTester::Config.testing_end_time}" +
|
89
91
|
" #{TasteTester::Config.timestamp_file}"
|
90
92
|
ssh << "echo -n '#{@serialized_config}' | base64 --decode" +
|
91
|
-
|
92
|
-
ssh <<
|
93
|
-
ssh <<
|
94
|
-
|
93
|
+
" > #{TasteTester::Config.chef_config_path}/client-taste-tester.rb"
|
94
|
+
ssh << "rm -vf #{TasteTester::Config.chef_config_path}/client.rb"
|
95
|
+
ssh << "( ln -vs #{TasteTester::Config.chef_config_path}" +
|
96
|
+
"/client-taste-tester.rb #{TasteTester::Config.chef_config_path}/" +
|
97
|
+
'client.rb; true )'
|
95
98
|
ssh.run!
|
96
99
|
|
97
100
|
# Then run any other stuff they wanted
|
@@ -113,19 +116,26 @@ module TasteTester
|
|
113
116
|
if TasteTester::Config.use_ssh_tunnels
|
114
117
|
TasteTester::Tunnel.kill(@name)
|
115
118
|
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
119
|
+
[
|
120
|
+
"rm -vf #{TasteTester::Config.chef_config_path}/client.rb",
|
121
|
+
"rm -vf #{TasteTester::Config.chef_config_path}/client-taste-tester.rb",
|
122
|
+
"ln -vs #{TasteTester::Config.chef_config_path}/client-prod.rb " +
|
123
|
+
"#{TasteTester::Config.chef_config_path}/client.rb",
|
124
|
+
"rm -vf #{TasteTester::Config.chef_config_path}/client.pem",
|
125
|
+
"ln -vs #{TasteTester::Config.chef_config_path}/client-prod.pem " +
|
126
|
+
"#{TasteTester::Config.chef_config_path}/client.pem",
|
127
|
+
"rm -vf #{TasteTester::Config.timestamp_file}",
|
128
|
+
'logger -t taste-tester Returning server to production',
|
129
|
+
].each do |cmd|
|
130
|
+
ssh << cmd
|
131
|
+
end
|
123
132
|
ssh.run!
|
124
133
|
end
|
125
134
|
|
126
135
|
def who_is_testing
|
127
136
|
ssh = TasteTester::SSH.new(@name)
|
128
|
-
ssh << 'grep "^# TasteTester by"
|
137
|
+
ssh << 'grep "^# TasteTester by"' +
|
138
|
+
" #{TasteTester::Config.chef_config_path}/client.rb"
|
129
139
|
output = ssh.run
|
130
140
|
if output.first == 0
|
131
141
|
user = output.last.match(/# TasteTester by (.*)$/)
|
@@ -136,7 +146,7 @@ module TasteTester
|
|
136
146
|
|
137
147
|
# Legacy FB stuff, remove after migration. Safe for everyone else.
|
138
148
|
ssh = TasteTester::SSH.new(@name)
|
139
|
-
ssh <<
|
149
|
+
ssh << "file #{TasteTester::Config.chef_config_path}/client.rb"
|
140
150
|
output = ssh.run
|
141
151
|
if output.first == 0
|
142
152
|
user = output.last.match(/client-(.*)-(taste-tester|test).rb/)
|
@@ -182,6 +192,7 @@ module TasteTester
|
|
182
192
|
else
|
183
193
|
url = "#{scheme}://#{@server.host}:#{TasteTester::State.port}"
|
184
194
|
end
|
195
|
+
# rubocop:disable Metrics/LineLength
|
185
196
|
ttconfig = <<-eos
|
186
197
|
# TasteTester by #{@user}
|
187
198
|
# Prevent people from screwing up their permissions
|
@@ -194,9 +205,10 @@ log_level :info
|
|
194
205
|
log_location STDOUT
|
195
206
|
chef_server_url '#{url}'
|
196
207
|
ssl_verify_mode :verify_none
|
197
|
-
Ohai::Config[:plugin_path] << '/
|
208
|
+
Ohai::Config[:plugin_path] << '#{TasteTester::Config.chef_config_path}/ohai_plugins'
|
198
209
|
|
199
210
|
eos
|
211
|
+
# rubocop:enable Metrics/LineLength
|
200
212
|
|
201
213
|
extra = TasteTester::Hooks.test_remote_client_rb_extra_code(@name)
|
202
214
|
if extra
|
data/lib/taste_tester/logging.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
data/lib/taste_tester/server.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -51,8 +51,8 @@ module TasteTester
|
|
51
51
|
# SSL and logging are obvious, but SSH is also required since it
|
52
52
|
# determines if we listen only on localhost or not
|
53
53
|
@need_restart = @state.ssl != TasteTester::Config.use_ssl ||
|
54
|
-
|
55
|
-
|
54
|
+
@state.logging != TasteTester::Config.chef_zero_logging ||
|
55
|
+
@state.ssh != TasteTester::Config.use_ssh_tunnels
|
56
56
|
|
57
57
|
# If we are using SSH tunneling listen on localhost, otherwise listen
|
58
58
|
# on all addresses - both v4 and v6. Note that on localhost, ::1 is
|
@@ -146,11 +146,11 @@ module TasteTester
|
|
146
146
|
def start_chef_zero
|
147
147
|
File.unlink(@log_file) if File.exists?(@log_file)
|
148
148
|
@state.update({
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
149
|
+
:port => TasteTester::Config.chef_port,
|
150
|
+
:ssl => TasteTester::Config.use_ssl,
|
151
|
+
:ssh => TasteTester::Config.use_ssh_tunnels,
|
152
|
+
:logging => TasteTester::Config.chef_zero_logging,
|
153
|
+
})
|
154
154
|
logger.info("Starting chef-zero of port #{@state.port}")
|
155
155
|
cmd = "#{chef_zero_path} --host #{@addr} --port #{@state.port} -d"
|
156
156
|
cmd << " --log-file #{@log_file}" if TasteTester::Config.chef_zero_logging
|
@@ -177,7 +177,7 @@ module TasteTester
|
|
177
177
|
].each do |path|
|
178
178
|
return path if File.exist?(path)
|
179
179
|
end
|
180
|
-
logger.error(
|
180
|
+
logger.error('chef-zero not found')
|
181
181
|
exit(1)
|
182
182
|
end
|
183
183
|
end
|
data/lib/taste_tester/ssh.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -46,7 +46,9 @@ module TasteTester
|
|
46
46
|
error = <<-MSG
|
47
47
|
SSH returned error while connecting to #{TasteTester::Config.user}@#{@host}
|
48
48
|
The host might be broken or your SSH access is not working properly
|
49
|
-
Try doing
|
49
|
+
Try doing
|
50
|
+
#{TasteTester::Config.ssh_command} -v #{TasteTester::Config.user}@#{@host}
|
51
|
+
and come back once that works
|
50
52
|
MSG
|
51
53
|
# rubocop:enable LineLength
|
52
54
|
error.lines.each { |x| logger.error x.strip }
|
@@ -61,8 +63,9 @@ MSG
|
|
61
63
|
logger.info("Will run: '#{cmd}' on #{@host}")
|
62
64
|
end
|
63
65
|
cmds = @cmds.join(' && ')
|
64
|
-
cmd = "
|
65
|
-
|
66
|
+
cmd = "#{TasteTester::Config.ssh_command} " +
|
67
|
+
"-T -o BatchMode=yes -o ConnectTimeout=#{@timeout} " +
|
68
|
+
"#{TasteTester::Config.user}@#{@host} "
|
66
69
|
if TasteTester::Config.user != 'root'
|
67
70
|
cc = Base64.encode64(cmds).gsub(/\n/, '')
|
68
71
|
cmd += "\"echo '#{cc}' | base64 --decode | sudo bash -x\""
|
data/lib/taste_tester/state.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -25,12 +25,12 @@ module TasteTester
|
|
25
25
|
# State of taste-tester processes
|
26
26
|
class State
|
27
27
|
include TasteTester::Config
|
28
|
-
|
28
|
+
extend TasteTester::Logging
|
29
29
|
include ::BetweenMeals::Util
|
30
30
|
|
31
31
|
def initialize
|
32
32
|
ref_dir = File.dirname(File.expand_path(
|
33
|
-
|
33
|
+
TasteTester::Config.ref_file
|
34
34
|
))
|
35
35
|
unless File.directory?(ref_dir)
|
36
36
|
begin
|
@@ -93,7 +93,7 @@ module TasteTester
|
|
93
93
|
|
94
94
|
def wipe
|
95
95
|
if TasteTester::Config.ref_file &&
|
96
|
-
|
96
|
+
File.exists?(TasteTester::Config.ref_file)
|
97
97
|
File.delete(TasteTester::Config.ref_file)
|
98
98
|
end
|
99
99
|
end
|
@@ -101,7 +101,7 @@ module TasteTester
|
|
101
101
|
private
|
102
102
|
|
103
103
|
def write(key, val)
|
104
|
-
merge({key => val})
|
104
|
+
merge({ key => val })
|
105
105
|
end
|
106
106
|
|
107
107
|
def merge(vals)
|
data/lib/taste_tester/tunnel.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -28,7 +28,7 @@ module TasteTester
|
|
28
28
|
@timeout = timeout
|
29
29
|
if TasteTester::Config.testing_until
|
30
30
|
@delta_secs = TasteTester::Config.testing_until.strftime('%s').to_i -
|
31
|
-
|
31
|
+
Time.now.strftime('%s').to_i
|
32
32
|
else
|
33
33
|
@delta_secs = TasteTester::Config.testing_time
|
34
34
|
end
|
@@ -49,23 +49,25 @@ module TasteTester
|
|
49
49
|
else
|
50
50
|
pid = '\\$\\$'
|
51
51
|
end
|
52
|
-
cmds = "ps -p #{pid} -o pgid | grep -v PGID
|
53
|
-
|
54
|
-
|
52
|
+
cmds = "ps -p #{pid} -o pgid | grep -v PGID" +
|
53
|
+
" > #{TasteTester::Config.timestamp_file} &&" +
|
54
|
+
" touch -t #{TasteTester::Config.testing_end_time}" +
|
55
|
+
" #{TasteTester::Config.timestamp_file} && sleep #{@delta_secs}"
|
55
56
|
# As great as it would be to have ExitOnForwardFailure=yes,
|
56
57
|
# we had multiple cases of tunnels dying
|
57
58
|
# if -f and ExitOnForwardFailure are used together.
|
58
59
|
# In most cases the first request from chef was "breaking" the tunnel,
|
59
60
|
# in a way that port was still open, but subsequent requests were hanging.
|
60
61
|
# This is reproducible and should be looked into.
|
61
|
-
cmd = "
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
cmd = "#{TasteTester::Config.ssh_command} " +
|
63
|
+
"-T -o BatchMode=yes -o ConnectTimeout=#{@timeout} " +
|
64
|
+
'-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ' +
|
65
|
+
'-o ServerAliveInterval=10 -o ServerAliveCountMax=6 ' +
|
66
|
+
"-f -R #{@port}:localhost:#{@server.port} "
|
65
67
|
if TasteTester::Config.user != 'root'
|
66
68
|
cc = Base64.encode64(cmds).gsub(/\n/, '')
|
67
69
|
cmd += "#{TasteTester::Config.user}@#{@host} \"echo '#{cc}' | base64" +
|
68
|
-
|
70
|
+
' --decode | sudo bash -x"'
|
69
71
|
else
|
70
72
|
cmd += "root@#{@host} \"#{cmds}\""
|
71
73
|
end
|
@@ -82,7 +84,8 @@ module TasteTester
|
|
82
84
|
sudo = 'sudo '
|
83
85
|
end
|
84
86
|
cmd = "( [ -s #{TasteTester::Config.timestamp_file} ]" +
|
85
|
-
|
87
|
+
" && #{sudo}kill -9 -- " +
|
88
|
+
"-\$(cat #{TasteTester::Config.timestamp_file}); true )"
|
86
89
|
ssh << cmd
|
87
90
|
ssh.run!
|
88
91
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: taste_tester
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Phil Dibowitz
|
@@ -16,10 +16,10 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2015-
|
19
|
+
date: 2015-11-26 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: between_meals >= 0.0.6
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: mixlib-config
|
37
37
|
prerelease: false
|
38
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
@@ -47,7 +47,7 @@ dependencies:
|
|
47
47
|
type: :runtime
|
48
48
|
version_requirements: *id002
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
50
|
+
name: colorize
|
51
51
|
prerelease: false
|
52
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
@@ -60,6 +60,48 @@ dependencies:
|
|
60
60
|
version: "0"
|
61
61
|
type: :runtime
|
62
62
|
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rubocop
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: chef-zero
|
79
|
+
prerelease: false
|
80
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
type: :development
|
90
|
+
version_requirements: *id005
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: knife-solo
|
93
|
+
prerelease: false
|
94
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
hash: 3
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
version: "0"
|
103
|
+
type: :development
|
104
|
+
version_requirements: *id006
|
63
105
|
description: Utility for testing Chef changes using chef-zero
|
64
106
|
email:
|
65
107
|
executables:
|
@@ -73,15 +115,15 @@ files:
|
|
73
115
|
- README.md
|
74
116
|
- LICENSE
|
75
117
|
- lib/taste_tester/host.rb
|
76
|
-
- lib/taste_tester/ssh.rb
|
77
|
-
- lib/taste_tester/tunnel.rb
|
78
|
-
- lib/taste_tester/server.rb
|
79
118
|
- lib/taste_tester/client.rb
|
80
119
|
- lib/taste_tester/hooks.rb
|
81
|
-
- lib/taste_tester/config.rb
|
82
|
-
- lib/taste_tester/logging.rb
|
83
|
-
- lib/taste_tester/state.rb
|
84
120
|
- lib/taste_tester/commands.rb
|
121
|
+
- lib/taste_tester/state.rb
|
122
|
+
- lib/taste_tester/ssh.rb
|
123
|
+
- lib/taste_tester/server.rb
|
124
|
+
- lib/taste_tester/tunnel.rb
|
125
|
+
- lib/taste_tester/logging.rb
|
126
|
+
- lib/taste_tester/config.rb
|
85
127
|
- bin/taste-tester
|
86
128
|
- scripts/taste-untester
|
87
129
|
homepage: https://github.com/facebook/taste-tester
|