taste_tester 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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 File.exists?(File.expand_path(TasteTester::Config.plugin_path))
339
- TasteTester::Hooks.get(File.expand_path(TasteTester::Config[:plugin_path]))
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
@@ -34,6 +34,7 @@ module TasteTester
34
34
  @knife = BetweenMeals::Knife.new(
35
35
  :logger => logger,
36
36
  :user => @server.user,
37
+ :ssl => TasteTester::Config.use_ssl,
37
38
  :host => @server.host,
38
39
  :port => @server.port,
39
40
  :role_dir => TasteTester::Config.roles,
@@ -108,7 +108,7 @@ module TasteTester
108
108
  def self.untest
109
109
  hosts = TasteTester::Config.servers
110
110
  unless hosts
111
- logger.warn('You must provide a hostname')
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 unless TasteTester::Server.running?
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
- errors = ['Cannot find a cookbook named', 'Connection reset by peer']
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
@@ -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 '/etc/taste-tester-plugin.rb'
38
- chef_zero_path '/opt/chef/embedded/bin/chef-zero'
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 true
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
@@ -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 = "http://localhost:#{@tunnel.port}"
181
+ url = "#{scheme}://localhost:#{@tunnel.port}"
181
182
  else
182
- url = "http://#{@server.host}:#{TasteTester::State.port}"
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 :info
193
- log_location STDOUT
194
- chef_server_url '#{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
- eos
199
+ eos
198
200
 
199
201
  extra = TasteTester::Hooks.test_remote_client_rb_extra_code(@name)
200
202
  if extra
@@ -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
- return if TasteTester::Server.running?
69
- logger.warn('Starting taste-tester server')
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
- unless @state.port
130
- @state.port = TasteTester::Config.chef_port
131
- end
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
- Mixlib::ShellOut.new(
135
- "#{chef_zero_path} --host #{@addr} --port #{@state.port} -d"
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',
@@ -51,6 +51,7 @@ MSG
51
51
  # rubocop:enable LineLength
52
52
  error.lines.each { |x| logger.error x.strip }
53
53
  logger.error(e.message)
54
+ exit(1)
54
55
  end
55
56
 
56
57
  private
@@ -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, value)
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[key.to_s] = value
113
+ state.merge!(vals)
82
114
  ff = File.open(
83
115
  TasteTester::Config.ref_file,
84
116
  'w'
@@ -44,13 +44,31 @@ module TasteTester
44
44
  end
45
45
 
46
46
  def cmd
47
- cmds = "echo \\\$\\\$ > #{TasteTester::Config.timestamp_file} &&" +
48
- " touch -t #{TasteTester::Config.testing_end_time}" +
49
- " #{TasteTester::Config.timestamp_file} && sleep #{@delta_secs}"
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
- "root@#{@host} \"#{cmds}\""
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
- ssh << "( [ -s #{TasteTester::Config.timestamp_file} ]" +
64
- " && kill -9 -- -\$(cat #{TasteTester::Config.timestamp_file}); true )"
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
- version: 0.0.7
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
- date: 2014-10-22 00:00:00.000000000 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
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
- version_requirements: !ruby/object:Gem::Requirement
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
- version: '0'
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
- version_requirements: !ruby/object:Gem::Requirement
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
- version: '0'
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
- version_requirements: !ruby/object:Gem::Requirement
52
+ requirement: &id003 !ruby/object:Gem::Requirement
58
53
  none: false
59
- requirements:
60
- - - ! '>='
61
- - !ruby/object:Gem::Version
62
- version: '0'
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
- extra_rdoc_files:
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/state.rb
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/server.rb
83
- - lib/taste_tester/ssh.rb
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
- require_paths:
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
- version: '0'
99
- required_rubygems_version: !ruby/object:Gem::Requirement
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
- version: '0'
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.29
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
+