taste_tester 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/taste-tester +7 -2
- data/lib/taste_tester/client.rb +1 -0
- data/lib/taste_tester/commands.rb +10 -3
- data/lib/taste_tester/config.rb +8 -6
- data/lib/taste_tester/host.rb +8 -6
- data/lib/taste_tester/server.rb +35 -9
- data/lib/taste_tester/ssh.rb +1 -0
- data/lib/taste_tester/state.rb +34 -2
- data/lib/taste_tester/tunnel.rb +29 -7
- metadata +78 -68
data/bin/taste-tester
CHANGED
@@ -335,8 +335,13 @@ MODES:
|
|
335
335
|
TasteTester::Logging.verbosity = TasteTester::Config.verbosity
|
336
336
|
TasteTester::Logging.use_log_formatter = TasteTester::Config.timestamp
|
337
337
|
|
338
|
-
if
|
339
|
-
|
338
|
+
if TasteTester::Config.plugin_path
|
339
|
+
path = File.expand_path(TasteTester::Config.plugin_path)
|
340
|
+
unless File.exists?(path)
|
341
|
+
logger.error("Plugin not found (#{path})")
|
342
|
+
exit(1)
|
343
|
+
end
|
344
|
+
TasteTester::Hooks.get(path)
|
340
345
|
end
|
341
346
|
|
342
347
|
case mode.to_sym
|
data/lib/taste_tester/client.rb
CHANGED
@@ -108,7 +108,7 @@ module TasteTester
|
|
108
108
|
def self.untest
|
109
109
|
hosts = TasteTester::Config.servers
|
110
110
|
unless hosts
|
111
|
-
logger.
|
111
|
+
logger.error('You must provide a hostname')
|
112
112
|
exit(1)
|
113
113
|
end
|
114
114
|
server = TasteTester::Server.new
|
@@ -152,14 +152,21 @@ module TasteTester
|
|
152
152
|
if TasteTester::Config.force_upload
|
153
153
|
server.restart
|
154
154
|
else
|
155
|
-
server.start
|
155
|
+
server.start
|
156
156
|
end
|
157
157
|
client = TasteTester::Client.new(server)
|
158
158
|
client.skip_checks = true if TasteTester::Config.skip_checks
|
159
159
|
client.force = true if TasteTester::Config.force_upload
|
160
160
|
client.upload
|
161
161
|
rescue => exception
|
162
|
-
|
162
|
+
# We're trying to recover from common chef-zero errors
|
163
|
+
# Most of them happen due to half finished uploads, which leave
|
164
|
+
# chef-zero in undefined state
|
165
|
+
errors = [
|
166
|
+
'Cannot find a cookbook named',
|
167
|
+
'Connection reset by peer',
|
168
|
+
'Object not found',
|
169
|
+
]
|
163
170
|
if errors.any? { |e| exception.to_s.match(/#{e}/im) }
|
164
171
|
TasteTester::Config.force_upload = true
|
165
172
|
unless @already_retried
|
data/lib/taste_tester/config.rb
CHANGED
@@ -34,8 +34,8 @@ module TasteTester
|
|
34
34
|
role_dir 'roles'
|
35
35
|
databag_dir 'databags'
|
36
36
|
config_file '/etc/taste-tester-config.rb'
|
37
|
-
plugin_path
|
38
|
-
chef_zero_path
|
37
|
+
plugin_path nil
|
38
|
+
chef_zero_path nil
|
39
39
|
verbosity Logger::WARN
|
40
40
|
timestamp false
|
41
41
|
user 'root'
|
@@ -47,7 +47,9 @@ module TasteTester
|
|
47
47
|
chef_port_range [5000, 5500]
|
48
48
|
tunnel_port 4001
|
49
49
|
timestamp_file '/etc/chef/test_timestamp'
|
50
|
-
use_ssh_tunnels
|
50
|
+
use_ssh_tunnels false
|
51
|
+
use_ssl true
|
52
|
+
chef_zero_logging true
|
51
53
|
|
52
54
|
skip_pre_upload_hook false
|
53
55
|
skip_post_upload_hook false
|
@@ -63,7 +65,7 @@ module TasteTester
|
|
63
65
|
|
64
66
|
def self.relative_cookbook_dirs
|
65
67
|
cookbook_dirs.map do |x|
|
66
|
-
File.join(base_dir, x)
|
68
|
+
(base_dir && !base_dir.empty?) ? File.join(base_dir, x) : x
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
@@ -72,7 +74,7 @@ module TasteTester
|
|
72
74
|
end
|
73
75
|
|
74
76
|
def self.relative_role_dir
|
75
|
-
File.join(base_dir, role_dir)
|
77
|
+
(base_dir && !base_dir.empty?) ? File.join(base_dir, role_dir) : x
|
76
78
|
end
|
77
79
|
|
78
80
|
def self.databags
|
@@ -80,7 +82,7 @@ module TasteTester
|
|
80
82
|
end
|
81
83
|
|
82
84
|
def self.relative_databag_dir
|
83
|
-
File.join(base_dir, databag_dir)
|
85
|
+
(base_dir && !base_dir.empty?) ? File.join(base_dir, databag_dir) : x
|
84
86
|
end
|
85
87
|
|
86
88
|
def self.chef_port
|
data/lib/taste_tester/host.rb
CHANGED
@@ -176,10 +176,11 @@ module TasteTester
|
|
176
176
|
private
|
177
177
|
|
178
178
|
def config
|
179
|
+
scheme = TasteTester::Config.use_ssl ? 'https' : 'http'
|
179
180
|
if TasteTester::Config.use_ssh_tunnels
|
180
|
-
url = "
|
181
|
+
url = "#{scheme}://localhost:#{@tunnel.port}"
|
181
182
|
else
|
182
|
-
url = "
|
183
|
+
url = "#{scheme}://#{@server.host}:#{TasteTester::State.port}"
|
183
184
|
end
|
184
185
|
ttconfig = <<-eos
|
185
186
|
# TasteTester by #{@user}
|
@@ -189,12 +190,13 @@ if Process.euid != 0
|
|
189
190
|
Process.exit!
|
190
191
|
end
|
191
192
|
|
192
|
-
log_level
|
193
|
-
log_location
|
194
|
-
chef_server_url
|
193
|
+
log_level :info
|
194
|
+
log_location STDOUT
|
195
|
+
chef_server_url '#{url}'
|
196
|
+
ssl_verify_mode :verify_none
|
195
197
|
Ohai::Config[:plugin_path] << '/etc/chef/ohai_plugins'
|
196
198
|
|
197
|
-
|
199
|
+
eos
|
198
200
|
|
199
201
|
extra = TasteTester::Hooks.test_remote_client_rb_extra_code(@name)
|
200
202
|
if extra
|
data/lib/taste_tester/server.rb
CHANGED
@@ -35,6 +35,7 @@ module TasteTester
|
|
35
35
|
@state = TasteTester::State.new
|
36
36
|
@ref_file = TasteTester::Config.ref_file
|
37
37
|
ref_dir = File.dirname(File.expand_path(@ref_file))
|
38
|
+
@log_file = "#{ref_dir}/chef-zero.log"
|
38
39
|
@zero_path = TasteTester::Config.chef_zero_path
|
39
40
|
unless File.directory?(ref_dir)
|
40
41
|
begin
|
@@ -47,6 +48,12 @@ module TasteTester
|
|
47
48
|
|
48
49
|
@user = ENV['USER']
|
49
50
|
|
51
|
+
# SSL and logging are obvious, but SSH is also required since it
|
52
|
+
# determines if we listen only on localhost or not
|
53
|
+
@need_restart = @state.ssl != TasteTester::Config.use_ssl ||
|
54
|
+
@state.logging != TasteTester::Config.chef_zero_logging ||
|
55
|
+
@state.ssh != TasteTester::Config.use_ssh_tunnels
|
56
|
+
|
50
57
|
# If we are using SSH tunneling listen on localhost, otherwise listen
|
51
58
|
# on all addresses - both v4 and v6. Note that on localhost, ::1 is
|
52
59
|
# v6-only, so we default to 127.0.0.1 instead.
|
@@ -65,8 +72,17 @@ module TasteTester
|
|
65
72
|
end
|
66
73
|
|
67
74
|
def start
|
68
|
-
|
69
|
-
|
75
|
+
if TasteTester::Server.running?
|
76
|
+
if @need_restart
|
77
|
+
logger.warn('Restarting taste-tester server for config change')
|
78
|
+
stop_chef_zero
|
79
|
+
@need_restart = false
|
80
|
+
else
|
81
|
+
return
|
82
|
+
end
|
83
|
+
else
|
84
|
+
logger.warn('Starting taste-tester server')
|
85
|
+
end
|
70
86
|
@state.wipe
|
71
87
|
write_config
|
72
88
|
start_chef_zero
|
@@ -82,6 +98,7 @@ module TasteTester
|
|
82
98
|
logger.warn('Restarting taste-tester server')
|
83
99
|
if TasteTester::Server.running?
|
84
100
|
stop_chef_zero
|
101
|
+
@state.ref = nil
|
85
102
|
end
|
86
103
|
write_config
|
87
104
|
start_chef_zero
|
@@ -116,6 +133,7 @@ module TasteTester
|
|
116
133
|
knife = BetweenMeals::Knife.new(
|
117
134
|
:logger => logger,
|
118
135
|
:user => @user,
|
136
|
+
:ssl => TasteTester::Config.use_ssl,
|
119
137
|
:host => @host,
|
120
138
|
:port => port,
|
121
139
|
:role_dir => TasteTester::Config.roles,
|
@@ -126,14 +144,18 @@ module TasteTester
|
|
126
144
|
end
|
127
145
|
|
128
146
|
def start_chef_zero
|
129
|
-
|
130
|
-
|
131
|
-
|
147
|
+
File.unlink(@log_file) if File.exists?(@log_file)
|
148
|
+
@state.update({
|
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
|
+
})
|
132
154
|
logger.info("Starting chef-zero of port #{@state.port}")
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
).run_command.error!
|
155
|
+
cmd = "#{chef_zero_path} --host #{@addr} --port #{@state.port} -d"
|
156
|
+
cmd << " --log-file #{@log_file}" if TasteTester::Config.chef_zero_logging
|
157
|
+
cmd << ' --ssl' if TasteTester::Config.use_ssl
|
158
|
+
Mixlib::ShellOut.new(cmd).run_command.error!
|
137
159
|
end
|
138
160
|
|
139
161
|
def stop_chef_zero
|
@@ -145,6 +167,10 @@ module TasteTester
|
|
145
167
|
end
|
146
168
|
|
147
169
|
def chef_zero_path
|
170
|
+
if TasteTester::Config.chef_zero_path
|
171
|
+
return TasteTester::Config.chef_zero_path
|
172
|
+
end
|
173
|
+
|
148
174
|
[
|
149
175
|
'/opt/chef/bin/chef-zero',
|
150
176
|
'/opt/chef/embedded/bin/chef-zero',
|
data/lib/taste_tester/ssh.rb
CHANGED
data/lib/taste_tester/state.rb
CHANGED
@@ -51,6 +51,30 @@ module TasteTester
|
|
51
51
|
write(:port, port)
|
52
52
|
end
|
53
53
|
|
54
|
+
def ssl
|
55
|
+
TasteTester::State.read(:ssl)
|
56
|
+
end
|
57
|
+
|
58
|
+
def ssl=(ssl)
|
59
|
+
write(:ssl, ssl)
|
60
|
+
end
|
61
|
+
|
62
|
+
def logging
|
63
|
+
TasteTester::State.read(:logging)
|
64
|
+
end
|
65
|
+
|
66
|
+
def logging=(logging)
|
67
|
+
write(:logging, logging)
|
68
|
+
end
|
69
|
+
|
70
|
+
def ssh
|
71
|
+
TasteTester::State.read(:ssh)
|
72
|
+
end
|
73
|
+
|
74
|
+
def ssh=(ssh)
|
75
|
+
write(:ssh, ssh)
|
76
|
+
end
|
77
|
+
|
54
78
|
def ref
|
55
79
|
TasteTester::State.read(:ref)
|
56
80
|
end
|
@@ -59,6 +83,10 @@ module TasteTester
|
|
59
83
|
write(:ref, ref)
|
60
84
|
end
|
61
85
|
|
86
|
+
def update(vals)
|
87
|
+
merge(vals)
|
88
|
+
end
|
89
|
+
|
62
90
|
def self.port
|
63
91
|
TasteTester::State.read(:port)
|
64
92
|
end
|
@@ -72,13 +100,17 @@ module TasteTester
|
|
72
100
|
|
73
101
|
private
|
74
102
|
|
75
|
-
def write(key,
|
103
|
+
def write(key, val)
|
104
|
+
merge({key => val})
|
105
|
+
end
|
106
|
+
|
107
|
+
def merge(vals)
|
76
108
|
begin
|
77
109
|
state = JSON.parse(File.read(TasteTester::Config.ref_file))
|
78
110
|
rescue
|
79
111
|
state = {}
|
80
112
|
end
|
81
|
-
state
|
113
|
+
state.merge!(vals)
|
82
114
|
ff = File.open(
|
83
115
|
TasteTester::Config.ref_file,
|
84
116
|
'w'
|
data/lib/taste_tester/tunnel.rb
CHANGED
@@ -44,13 +44,31 @@ module TasteTester
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def cmd
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
if TasteTester::Config.user != 'root'
|
48
|
+
pid = '$$'
|
49
|
+
else
|
50
|
+
pid = '\\$\\$'
|
51
|
+
end
|
52
|
+
cmds = "ps -p #{pid} -o pgid | grep -v PGID > #{TasteTester::Config.timestamp_file} &&" +
|
53
|
+
" touch -t #{TasteTester::Config.testing_end_time}" +
|
54
|
+
" #{TasteTester::Config.timestamp_file} && sleep #{@delta_secs}"
|
55
|
+
# As great as it would be to have ExitOnForwardFailure=yes,
|
56
|
+
# we had multiple cases of tunnels dying
|
57
|
+
# if -f and ExitOnForwardFailure are used together.
|
58
|
+
# In most cases the first request from chef was "breaking" the tunnel,
|
59
|
+
# in a way that port was still open, but subsequent requests were hanging.
|
60
|
+
# This is reproducible and should be looked into.
|
50
61
|
cmd = "ssh -T -o BatchMode=yes -o ConnectTimeout=#{@timeout} " +
|
62
|
+
'-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ' +
|
51
63
|
'-o ServerAliveInterval=10 -o ServerAliveCountMax=6 ' +
|
52
|
-
"-f -R #{@port}:localhost:#{@server.port} "
|
53
|
-
|
64
|
+
"-f -R #{@port}:localhost:#{@server.port} "
|
65
|
+
if TasteTester::Config.user != 'root'
|
66
|
+
cc = Base64.encode64(cmds).gsub(/\n/, '')
|
67
|
+
cmd += "#{TasteTester::Config.user}@#{@host} \"echo '#{cc}' | base64" +
|
68
|
+
' --decode | sudo bash -x"'
|
69
|
+
else
|
70
|
+
cmd += "root@#{@host} \"#{cmds}\""
|
71
|
+
end
|
54
72
|
cmd
|
55
73
|
end
|
56
74
|
|
@@ -60,8 +78,12 @@ module TasteTester
|
|
60
78
|
# surround this in paryns, and make sure as a whole it evaluates
|
61
79
|
# to true so it doesn't mess up other things... even though this is
|
62
80
|
# the only thing we're currently executing in this SSH.
|
63
|
-
|
64
|
-
|
81
|
+
if TasteTester::Config.user != 'root'
|
82
|
+
sudo = 'sudo '
|
83
|
+
end
|
84
|
+
cmd = "( [ -s #{TasteTester::Config.timestamp_file} ]" +
|
85
|
+
" && #{sudo}kill -9 -- -\$(cat #{TasteTester::Config.timestamp_file}); true )"
|
86
|
+
ssh << cmd
|
65
87
|
ssh.run!
|
66
88
|
end
|
67
89
|
end
|
metadata
CHANGED
@@ -1,111 +1,121 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: taste_tester
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 8
|
10
|
+
version: 0.0.8
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Phil Dibowitz
|
9
14
|
- Marcin Sawicki
|
10
15
|
autorequire:
|
11
16
|
bindir: bin
|
12
17
|
cert_chain: []
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
|
19
|
+
date: 2015-01-05 00:00:00 Z
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
16
22
|
name: mixlib-config
|
17
|
-
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
|
-
requirements:
|
20
|
-
- - ! '>='
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '0'
|
23
|
-
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
|
26
|
-
none: false
|
27
|
-
requirements:
|
28
|
-
- - ! '>='
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
version: '0'
|
31
|
-
- !ruby/object:Gem::Dependency
|
32
|
-
name: colorize
|
33
|
-
requirement: !ruby/object:Gem::Requirement
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
34
25
|
none: false
|
35
|
-
requirements:
|
36
|
-
- -
|
37
|
-
- !ruby/object:Gem::Version
|
38
|
-
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
39
33
|
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: colorize
|
40
37
|
prerelease: false
|
41
|
-
|
42
|
-
none: false
|
43
|
-
requirements:
|
44
|
-
- - ! '>='
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '0'
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: between_meals
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
50
39
|
none: false
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
55
47
|
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: between_meals
|
56
51
|
prerelease: false
|
57
|
-
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
53
|
none: false
|
59
|
-
requirements:
|
60
|
-
- -
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
63
|
description: Utility for testing Chef changes using chef-zero
|
64
64
|
email:
|
65
|
-
executables:
|
65
|
+
executables:
|
66
66
|
- taste-tester
|
67
67
|
extensions: []
|
68
|
-
|
68
|
+
|
69
|
+
extra_rdoc_files:
|
69
70
|
- README.md
|
70
71
|
- LICENSE
|
71
|
-
files:
|
72
|
+
files:
|
72
73
|
- README.md
|
73
74
|
- LICENSE
|
74
|
-
- lib/taste_tester/hooks.rb
|
75
|
-
- lib/taste_tester/logging.rb
|
76
|
-
- lib/taste_tester/commands.rb
|
77
|
-
- lib/taste_tester/tunnel.rb
|
78
75
|
- lib/taste_tester/host.rb
|
79
|
-
- lib/taste_tester/
|
76
|
+
- lib/taste_tester/ssh.rb
|
77
|
+
- lib/taste_tester/tunnel.rb
|
78
|
+
- lib/taste_tester/server.rb
|
80
79
|
- lib/taste_tester/client.rb
|
80
|
+
- lib/taste_tester/hooks.rb
|
81
81
|
- lib/taste_tester/config.rb
|
82
|
-
- lib/taste_tester/
|
83
|
-
- lib/taste_tester/
|
82
|
+
- lib/taste_tester/logging.rb
|
83
|
+
- lib/taste_tester/state.rb
|
84
|
+
- lib/taste_tester/commands.rb
|
84
85
|
- bin/taste-tester
|
85
86
|
- scripts/taste-untester
|
86
87
|
homepage: https://github.com/facebook/taste-tester
|
87
|
-
licenses:
|
88
|
+
licenses:
|
88
89
|
- Apache
|
89
90
|
post_install_message:
|
90
91
|
rdoc_options: []
|
91
|
-
|
92
|
+
|
93
|
+
require_paths:
|
92
94
|
- lib
|
93
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
96
|
none: false
|
95
|
-
requirements:
|
96
|
-
- -
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
|
99
|
-
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
105
|
none: false
|
101
|
-
requirements:
|
102
|
-
- -
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 3
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
version: "0"
|
105
113
|
requirements: []
|
114
|
+
|
106
115
|
rubyforge_project:
|
107
|
-
rubygems_version: 1.8.
|
116
|
+
rubygems_version: 1.8.5
|
108
117
|
signing_key:
|
109
118
|
specification_version: 3
|
110
119
|
summary: Taste Tester
|
111
120
|
test_files: []
|
121
|
+
|