rspec-system 2.2.1 → 2.3.0

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/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ 2.3.0
2
+ =====
3
+
4
+ Rework the look and feel to make it pretty and add color
5
+
6
+ This feature release is primarily a look and feel update that improves the visual look of
7
+ how tests run. It changes the way `shell` and `rcp` output looks and includes
8
+ more color where applicable.
9
+
10
+ The output now uses the formatters output methods, in a mildly hackish way so
11
+ that colors can be disabled centrally and also so if users switch to a different
12
+ format the output is silenced. This is useful for cases where you want to run
13
+ the progress formatter without all the extra noise for example.
14
+
15
+ The dividers are now a little better, showing you the begin and end of blocks
16
+ in a better way now, so it is slightly easier to see before/after runs
17
+ without them bleeding into the test parts.
18
+
19
+ As an aside I've also migrated the scp methodology from vsphere to vagrant so
20
+ we are using the same channel to transfer files as well as for sending commands
21
+ which should in theory be a perf boost, but as yet I've seen little evidence.
22
+
23
+ #### Detailed Changes
24
+
25
+ * Rework the look and feel to make it pretty and add color (Ken Barber)
26
+
27
+ -------------------------------
28
+
1
29
  2.2.1
2
30
  =====
3
31
 
@@ -24,7 +24,7 @@ module RSpecSystem
24
24
  def start(count)
25
25
  @max_tests = count
26
26
  super(count)
27
- output << "=================================================================\n\n"
27
+ output << "\n"
28
28
  output << bold("Commencing rspec-system tests\n")
29
29
  output << bold("Total Test Count: ") << color(count, :cyan) << "\n\n"
30
30
  end
@@ -35,7 +35,7 @@ module RSpecSystem
35
35
  # @return [void]
36
36
  def example_started(example)
37
37
  super(example)
38
- output << "=================================================================\n\n"
38
+ output << "\n=begin===========================================================\n\n"
39
39
  output << bold("Running test: ") << "#{next_index} of #{@max_tests}" << "\n"
40
40
  output << bold("Description:\n ") << color(example.full_description, :magenta) << "\n\n"
41
41
  end
@@ -47,6 +47,7 @@ module RSpecSystem
47
47
  def example_passed(example)
48
48
  super(example)
49
49
  output << "\n" << bold('Result: ') << success_color('passed') << "\n\n"
50
+ output << "=end=============================================================\n\n"
50
51
  end
51
52
 
52
53
  # Display output when an example is pending
@@ -58,6 +59,7 @@ module RSpecSystem
58
59
  msg = example.execution_result[:pending_message]
59
60
  output << "\n" << bold('Result: ') << pending_color('pending') << "\n"
60
61
  output << bold("Reason: ") << "#{msg}\n\n"
62
+ output << "=end=============================================================\n\n"
61
63
  end
62
64
 
63
65
  # Display output when an example has failed
@@ -69,6 +71,7 @@ module RSpecSystem
69
71
  msg = example.execution_result[:exception]
70
72
  output << "\n" << bold('Result: ') << failure_color('failed') << "\n"
71
73
  output << bold("Reason:\n") << "#{msg}\n\n"
74
+ output << "=end=============================================================\n\n"
72
75
  end
73
76
 
74
77
  # Obtains next index value so we can keep a count of what test we are upto
@@ -37,7 +37,6 @@ module RSpecSystem::Helpers
37
37
  sp = opts[:sp]
38
38
  dp = opts[:dp]
39
39
 
40
- log.info("rcp from #{sp} to #{d.name}:#{dp} executed")
41
40
  result = ns.rcp(opts)
42
41
  { :success => result }
43
42
  end
@@ -31,6 +31,10 @@ module RSpecSystem::Helpers
31
31
 
32
32
  # Gathers new results by executing the resource action
33
33
  def execute
34
+ dest = opts[:n].name
35
+ cmd = opts[:c]
36
+
37
+ output << bold(color("#{dest}$", :green)) << " #{cmd}\n"
34
38
  rspec_system_node_set.run(opts)
35
39
  end
36
40
  end
@@ -67,20 +67,20 @@ module RSpecSystem::InternalHelpers
67
67
  def start_nodes
68
68
  ns = rspec_system_node_set
69
69
 
70
- puts "Starting nodes"
71
- puts
72
- puts "Setname is: " + ns.setname
73
- puts "Configuration is: " + ns.config.pretty_inspect
74
- puts "Virtual Environment type is: #{ns.env_type}"
75
- puts "Default node is: #{ns.default_node.name}"
76
- puts "Destroy node is: #{ns.destroy}"
77
- puts
78
-
70
+ output << "=begin===========================================================\n"
71
+ output << "\n"
72
+ output << bold("Starting nodes") << "\n"
73
+ output << "\n"
74
+ output << bold("Setname:") << " #{ns.setname}\n"
75
+ output << bold("Configuration:") << " #{ns.config.pretty_inspect}"
76
+ output << bold("Virtual Environment:") << " #{ns.env_type}\n"
77
+ output << bold("Default node:") << " #{ns.default_node.name}\n"
78
+ output << bold("Destroy node:") << " #{ns.destroy}\n"
79
+ output << "\n"
79
80
  ns.setup
80
-
81
- puts
82
- puts "Finished starting nodes"
83
- puts "================================================================="
81
+ output << "\n"
82
+ output << "=end=============================================================\n"
83
+ output << "\n"
84
84
  nil
85
85
  end
86
86
 
@@ -88,11 +88,14 @@ module RSpecSystem::InternalHelpers
88
88
  #
89
89
  # @return [void]
90
90
  def stop_nodes
91
- puts 'Stopping nodes'
92
- puts
91
+ output << "\n"
92
+ output << "=begin===========================================================\n"
93
+ output << "\n"
94
+ output << bold("Stopping nodes\n")
95
+ output << "\n"
93
96
  rspec_system_node_set.teardown
94
- puts 'Finished stopping nodes'
95
- puts "================================================================="
97
+ output << "\n"
98
+ output << "=end=============================================================\n"
96
99
  nil
97
100
  end
98
101
  end
@@ -2,16 +2,80 @@ require 'logger'
2
2
 
3
3
  # This log overlay module, provides access to the +log+ method.
4
4
  module RSpecSystem::Log
5
+ class Logger
6
+ attr_accessor :io
7
+
8
+ def initialize(io)
9
+ @io = io
10
+ end
11
+
12
+ def debug(text)
13
+ io << bold(color('Debug: ', :blue)) << text << "\n"
14
+ end
15
+
16
+ def info(text)
17
+ io << bold('Info: ') << text << "\n"
18
+ end
19
+
20
+ def warn(text)
21
+ io << 'Warn: ' << text << "\n"
22
+ end
23
+
24
+ def fatal(text)
25
+ io << 'Fatal: ' << text << "\n"
26
+ end
27
+
28
+ def unknown(text)
29
+ io << 'Unknown: ' << text << "\n"
30
+ end
31
+
32
+ def error(text)
33
+ io << 'Error: ' << text << "\n"
34
+ end
35
+ end
36
+
5
37
  # Return the default Logger object.
6
38
  #
7
39
  # @return [Logger] default logger object
8
40
  def log
9
41
  return @logger if @logger
10
- @logger = ::Logger.new(STDOUT)
11
- @logger.progname = 'rspec-system'
12
- @logger.formatter = Proc.new do |s, t, p, m|
13
- "#{s}: #{m}\n"
14
- end
42
+ @logger = Logger.new(output)
15
43
  @logger
16
44
  end
45
+
46
+ def formatter
47
+ RSpec.configuration.formatters.each do |f|
48
+ if f.is_a? RSpecSystem::Formatter then
49
+ return f
50
+ end
51
+ end
52
+ end
53
+
54
+ class NullStream
55
+ def <<(o); self; end
56
+ end
57
+
58
+ def output
59
+ begin
60
+ formatter.output
61
+ rescue NameError
62
+ NullStream.new
63
+ end
64
+ end
65
+
66
+ def bold(text)
67
+ begin
68
+ formatter.send(:bold, text)
69
+ rescue NameError
70
+ ""
71
+ end
72
+ end
73
+
74
+ def color(text, color)
75
+ begin
76
+ formatter.send(:color, text, color)
77
+ rescue NameError
78
+ ""
79
+ end
80
+ end
17
81
  end
@@ -127,25 +127,25 @@ module RSpecSystem
127
127
  end
128
128
  channel.on_data do |ch,data|
129
129
  d = data
130
- print d
130
+ output << d
131
131
  r[:stdout]+=d
132
132
  end
133
133
 
134
134
  channel.on_extended_data do |ch,type,data|
135
135
  d = data
136
- print d
136
+ output << d
137
137
  r[:stderr]+=d
138
138
  end
139
139
 
140
140
  channel.on_request("exit-status") do |ch,data|
141
141
  c = data.read_long
142
- puts "Exit code: #{c}"
142
+ output << bold("Exit code:") << " #{c}\n"
143
143
  r[:exit_code] = c
144
144
  end
145
145
 
146
146
  channel.on_request("exit-signal") do |ch, data|
147
147
  s = data.read_string
148
- puts "Exit signal: #{s}"
148
+ output << bold("Exit signal:") << " #{s}\n"
149
149
  r[:exit_signal] = s
150
150
  end
151
151
  end
@@ -19,29 +19,30 @@ module RSpecSystem
19
19
  def initialize(setname, config, custom_prefabs_path, options)
20
20
  super
21
21
  @vagrant_path = File.expand_path(File.join(RSpec.configuration.system_tmp, 'vagrant_projects', setname))
22
+
23
+ RSpec.configuration.rspec_storage[:nodes] ||= {}
22
24
  end
23
25
 
24
26
  # Setup the NodeSet by starting all nodes.
25
27
  #
26
28
  # @return [void]
27
29
  def setup
28
- log.info "[Vagrant#setup] Begin setting up vagrant"
29
-
30
30
  create_vagrantfile()
31
31
 
32
32
  teardown()
33
33
 
34
- log.info "[Vagrant#setup] Running 'vagrant up'"
34
+ output << bold(color("localhost$", :green)) << " vagrant up\n"
35
35
  vagrant("up")
36
36
 
37
37
  # Establish ssh connectivity
38
- ssh_channels = {}
39
38
  nodes.each do |k,v|
40
- log.info "[Vagrant#setup] establishing Net::SSH channel with #{k}"
39
+ output << bold(color("localhost$", :green)) << " ssh #{k}\n"
41
40
  chan = Net::SSH.start(k, 'vagrant', :config => ssh_config)
42
- ssh_channels[k] = chan
41
+
42
+ RSpec.configuration.rspec_storage[:nodes][k] = {
43
+ :ssh => chan,
44
+ }
43
45
  end
44
- RSpec.configuration.ssh_channels = ssh_channels
45
46
 
46
47
  nil
47
48
  end
@@ -50,16 +51,18 @@ module RSpecSystem
50
51
  #
51
52
  # @return [void]
52
53
  def teardown
53
- log.info "[Vagrant#teardown] closing all ssh channels"
54
- RSpec.configuration.ssh_channels.each do |k,v|
55
- v.close unless v.closed?
54
+ nodes.each do |k,v|
55
+ storage = RSpec.configuration.rspec_storage[:nodes][k]
56
+
57
+ next if storage.nil?
58
+
59
+ ssh = storage[:ssh]
60
+ ssh.close unless ssh.closed?
56
61
  end
57
62
 
58
63
  if destroy
59
- log.info "[Vagrant#teardown] Running 'vagrant destroy'"
64
+ output << bold(color("localhost$", :green)) << " vagrant destroy --force\n"
60
65
  vagrant("destroy --force")
61
- else
62
- log.info "[Vagrant#teardown] Skipping 'vagrant destroy'"
63
66
  end
64
67
  nil
65
68
  end
@@ -72,12 +75,8 @@ module RSpecSystem
72
75
  dest = opts[:n].name
73
76
  cmd = opts[:c]
74
77
 
75
- ssh_channels = RSpec.configuration.ssh_channels
76
- puts "-----------------"
77
- puts "#{dest}$ #{cmd}"
78
- result = ssh_exec!(ssh_channels[dest], "cd /tmp && sudo sh -c #{shellescape(cmd)}")
79
- puts "-----------------"
80
- result
78
+ ssh = RSpec.configuration.rspec_storage[:nodes][dest][:ssh]
79
+ ssh_exec!(ssh, "cd /tmp && sudo sh -c #{shellescape(cmd)}")
81
80
  end
82
81
 
83
82
  # Transfer files to a host in the NodeSet.
@@ -88,8 +87,6 @@ module RSpecSystem
88
87
  # path then move it later. Its slow and brittle and we need a better
89
88
  # solution. Its also very Linux-centrix in its use of temp dirs.
90
89
  def rcp(opts)
91
- #log.debug("[Vagrant@rcp] called with #{opts.inspect}")
92
-
93
90
  dest = opts[:d].name
94
91
  source = opts[:sp]
95
92
  dest_path = opts[:dp]
@@ -98,23 +95,13 @@ module RSpecSystem
98
95
  tmpdest = tmppath
99
96
 
100
97
  # Do the copy and print out results for debugging
101
- cmd = "scp -r -F '#{ssh_config}' '#{source}' #{dest}:#{tmpdest}"
102
- puts "------------------"
103
- puts "localhost$ #{cmd}"
104
- r = systemu cmd
105
-
106
- result = {
107
- :exit_code => r[0].exitstatus,
108
- :stdout => r[1],
109
- :stderr => r[2]
110
- }
111
-
112
- print "#{result[:stdout]}"
113
- print "#{result[:stderr]}"
114
- puts "Exit code: #{result[:exit_code]}"
98
+ cmd = "scp -r '#{source}' #{dest}:#{tmpdest}"
99
+ output << bold(color("localhost$", :green)) << " #{cmd}\n"
100
+ ssh = RSpec.configuration.rspec_storage[:nodes][dest][:ssh]
101
+ ssh.scp.upload! source.to_s, tmpdest.to_s, :recursive => true
115
102
 
116
103
  # Now we move the file into their final destination
117
- result = run(:n => opts[:d], :c => "mv #{tmpdest} #{dest_path}")
104
+ result = shell(:n => opts[:d], :c => "mv #{tmpdest} #{dest_path}")
118
105
  if result[:exit_code] == 0
119
106
  return true
120
107
  else
@@ -126,13 +113,11 @@ module RSpecSystem
126
113
  #
127
114
  # @api private
128
115
  def create_vagrantfile
129
- log.info "[Vagrant#create_vagrantfile] Creating vagrant file here: #{@vagrant_path}"
116
+ output << bold(color("localhost$", :green)) << " cd #{@vagrant_path}\n"
130
117
  FileUtils.mkdir_p(@vagrant_path)
131
118
  File.open(File.expand_path(File.join(@vagrant_path, "Vagrantfile")), 'w') do |f|
132
119
  f.write('Vagrant.configure("2") do |c|' + "\n")
133
120
  nodes.each do |k,v|
134
- log.debug "Filling in content for #{k}"
135
-
136
121
  ps = v.provider_specifics['vagrant']
137
122
 
138
123
  node_config = " c.vm.define '#{k}' do |v|\n"
@@ -148,7 +133,6 @@ module RSpecSystem
148
133
  end
149
134
  f.write("end\n")
150
135
  end
151
- log.debug "[Vagrant#create_vagrantfile] Finished creating vagrant file"
152
136
  nil
153
137
  end
154
138
 
@@ -167,7 +151,6 @@ module RSpecSystem
167
151
  self.nodes.each do |k,v|
168
152
  Dir.chdir(@vagrant_path) do
169
153
  result = systemu("vagrant ssh-config #{k} >> #{ssh_config_path}")
170
- puts result.inspect
171
154
  end
172
155
  end
173
156
  ssh_config_path
@@ -37,8 +37,6 @@ module RSpecSystem
37
37
  #
38
38
  # @return [void]
39
39
  def setup
40
- log.info "[Vsphere#setup] Setup begins"
41
-
42
40
  dest_dir = ENV['RSPEC_VSPHERE_DEST_DIR']
43
41
  template_dir = ENV['RSPEC_VSPHERE_TEMPLATE_DIR']
44
42
 
@@ -56,7 +54,7 @@ module RSpecSystem
56
54
  vm_folder = dc.vmFolder
57
55
  vm_newfolder = vm_folder.find(dest_dir)
58
56
 
59
- log.info "[Vsphere#setup] launching instances one by one"
57
+ log.info "Launching VSphere instances one by one"
60
58
  nodes.each do |k,v|
61
59
  ps = v.provider_specifics['vsphere']
62
60
 
@@ -66,7 +64,7 @@ module RSpecSystem
66
64
 
67
65
  raise "No template specified for this prefab" if template.nil?
68
66
 
69
- log.info "[Vsphere#setup] launching instance #{k} with template #{template}"
67
+ log.info "Launching VSphere instance #{k} with template #{template}"
70
68
 
71
69
  vm = vm_folder.find(ENV['RSPEC_VSPHERE_TEMPLATE_DIR']).find(template)
72
70
 
@@ -74,7 +72,7 @@ module RSpecSystem
74
72
 
75
73
  vm_name = "rspec-system-#{k}-#{random_string(10)}"
76
74
 
77
- log.info "[Vsphere#setup] Cloning new vm #{vm_name} in folder #{dest_dir}"
75
+ log.info "Cloning new VSphere vm #{vm_name} in folder #{dest_dir}"
78
76
 
79
77
  vm.CloneVM_Task(
80
78
  :folder => vm_newfolder,
@@ -82,7 +80,7 @@ module RSpecSystem
82
80
  :spec => spec
83
81
  ).wait_for_completion
84
82
 
85
- log.info "[Vsphere#setup] Cloning complete"
83
+ log.info "Cloning complete"
86
84
 
87
85
  newvm = vm_newfolder.find(vm_name)
88
86
  guest_info = newvm.guest
@@ -90,20 +88,20 @@ module RSpecSystem
90
88
  timeout(60) do
91
89
  while(newvm.guest.guestState != 'running') do
92
90
  sleep 2
93
- puts "#{k}> Waiting for vm to run ..."
91
+ log.info "#{k}> Waiting for vm to run ..."
94
92
  end
95
93
  end
96
94
 
97
95
  timeout(60) do
98
96
  while(newvm.guest.ipAddress == nil) do
99
97
  sleep 2
100
- puts "#{k}> Waiting for ip address ..."
98
+ log.info "#{k}> Waiting for ip address ..."
101
99
  end
102
100
  end
103
101
 
104
102
  ipaddress = newvm.guest.ipAddress
105
103
 
106
- log.info "[Vsphere#setup] establishing Net::SSH channel with #{k}"
104
+ output << bold(color("localhost$", :green)) << " ssh #{k}"
107
105
  chan = Net::SSH.start(ipaddress, 'vagrant', :password => 'vagrant')
108
106
 
109
107
  RSpec.configuration.rspec_storage[:nodes][k] = {
@@ -111,11 +109,8 @@ module RSpecSystem
111
109
  :ssh => chan,
112
110
  :vm => newvm
113
111
  }
114
- log.info "[Vsphere#setup] Node launched: #{k}"
115
112
  end
116
113
 
117
- log.info("[Vsphere#setup] setup complete")
118
-
119
114
  nil
120
115
  end
121
116
 
@@ -127,25 +122,23 @@ module RSpecSystem
127
122
  storage = RSpec.configuration.rspec_storage[:nodes][k]
128
123
 
129
124
  if storage.nil?
130
- log.info "[Vsphere#teardown] No entry for node #{k}, no teardown necessary"
125
+ log.info "No entry for node #{k}, no teardown necessary"
131
126
  next
132
127
  end
133
128
 
134
- log.info "[Vsphere#teardown] closing ssh channel to #{k}"
135
129
  ssh = storage[:ssh]
136
130
  ssh.close unless ssh.closed?
137
131
 
138
132
  if destroy
139
- log.info "[Vsphere#teardown] destroy instance #{k}"
133
+ log.info "Destroying instance #{k}"
140
134
  vm = storage[:vm]
141
135
  if vm == nil
142
- puts "No vm object"
136
+ log.error "No vm object for #{k}"
143
137
  next
144
138
  end
145
139
  vm.PowerOffVM_Task.wait_for_completion
146
140
  vm.Destroy_Task.wait_for_completion
147
141
  else
148
- log.info "[Vsphere#teardown] Skipping destroy instance #{k}"
149
142
  next
150
143
  end
151
144
  end
@@ -162,11 +155,7 @@ module RSpecSystem
162
155
  cmd = opts[:c]
163
156
 
164
157
  ssh = RSpec.configuration.rspec_storage[:nodes][dest][:ssh]
165
- puts "-----------------"
166
- puts "#{dest}$ #{cmd}"
167
- result = ssh_exec!(ssh, "cd /tmp && sudo sh -c '#{cmd}'")
168
- puts "-----------------"
169
- result
158
+ ssh_exec!(ssh, "cd /tmp && sudo sh -c '#{cmd}'")
170
159
  end
171
160
 
172
161
  # Transfer files to a host in the NodeSet.
@@ -177,8 +166,6 @@ module RSpecSystem
177
166
  # path then move it later. Its slow and brittle and we need a better
178
167
  # solution. Its also very Linux-centrix in its use of temp dirs.
179
168
  def rcp(opts)
180
- #log.debug("[Vagrant@rcp] called with #{opts.inspect}")
181
-
182
169
  dest = opts[:d].name
183
170
  source = opts[:sp]
184
171
  dest_path = opts[:dp]
@@ -29,20 +29,19 @@ RSpec.configure do |c|
29
29
  begin
30
30
  start_nodes
31
31
  rescue => ex
32
- puts ex.inspect + " in"
33
- puts ex.backtrace.join("\n ")
32
+ output << ex.inspect + " in\n"
33
+ output << ex.backtrace.join("\n ") << "\n"
34
34
  exit(1)
35
35
  end
36
36
  end
37
37
 
38
38
  c.after :suite do
39
- puts "================================================================="
40
39
  # After Suite exceptions get captured it seems
41
40
  begin
42
41
  stop_nodes
43
42
  rescue => ex
44
- puts ex.inspect + " in"
45
- puts ex.backtrace.join("\n ")
43
+ output << ex.inspect + " in\n"
44
+ output << ex.backtrace.join("\n ") << "\n"
46
45
  end
47
46
  end
48
47
  end
data/rspec-system.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
  Gem::Specification.new do |s|
3
3
  # Metadata
4
4
  s.name = "rspec-system"
5
- s.version = "2.2.1"
5
+ s.version = "2.3.0"
6
6
  s.authors = ["Ken Barber"]
7
7
  s.email = ["info@puppetlabs.com"]
8
8
  s.homepage = "https://github.com/puppetlabs/rspec-system"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-system
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
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-09-11 00:00:00.000000000 Z
12
+ date: 2013-09-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -217,4 +217,3 @@ test_files:
217
217
  - spec/unit/kwalify-schemas/prefabs_schema_spec.rb
218
218
  - spec/unit/result_spec.rb
219
219
  - spec/unit/utils_spec.rb
220
- has_rdoc: