Skip to content

Commit

Permalink
(puppetlabsGH-2543) Block publishing events while prompting and parallel
Browse files Browse the repository at this point in the history
This will block the executor from continuing to publish events until the
user has entered input for a prompt. This prevents prompts inside of
parallelize blocks from being interleaved with output from the block
continuing to execute.

This also adds a known issue that output from `resolve_reference` that
uses `prompt` inside a parallel block may not be a good user experience.

Lastly, this adjusts the spinner while running in parallel to
pessimistically spin - that is, only spin if it's started by a
long-running process and not stopped. This includes sending the `spin:
stop` message to the spinner at any point that a
non-long-running-process (like prompt) might begin.

Closes puppetlabs#2543

!bug

* **Don't continue executing parallel block when prompting** ([puppetlabs#2543](puppetlabs#2543))
  Bolt will now pause printing messages from parallel blocks when
  prompting the user for input, to avoid confusing printing to the screen.
  • Loading branch information
lucywyman authored and beechtom committed Jan 21, 2021
1 parent 1cc58b8 commit 0df4785
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 7 deletions.
7 changes: 5 additions & 2 deletions lib/bolt/executor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ def publish_event(event)
# that type of event, publish the event
next unless types.nil? || types.include?(event[:type])
@publisher.post(subscriber) do |sub|
# Wait for user to input to prompt before printing anything
sleep(0.1) while @prompting
sub.handle_event(event)
end
end
Expand Down Expand Up @@ -412,7 +414,7 @@ def round_robin(skein)
subscribe(self, [:node_result])
results = Array.new(skein.length)
@in_parallel = true
publish_event(type: :start_spin)
publish_event(type: :stop_spin)

until skein.empty?
@thread_completed = false
Expand Down Expand Up @@ -474,18 +476,19 @@ def wait_until(timeout, retry_interval)
end

def prompt(prompt, options)
@prompting = true
unless $stdin.tty?
raise Bolt::Error.new('STDIN is not a tty, unable to prompt', 'bolt/no-tty-error')
end

sleep(0.1) if @in_parallel
$stderr.print("#{prompt}: ")

value = if options[:sensitive]
$stdin.noecho(&:gets).to_s.chomp
else
$stdin.gets.to_s.chomp
end
@prompting = false

$stderr.puts if options[:sensitive]

Expand Down
6 changes: 3 additions & 3 deletions lib/bolt/outputter/rainbow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ def colorize(color, string)
end

def start_spin
return unless @spin && @stream.isatty
@spin = true
return unless @spin && @stream.isatty && !@spinning
@spinning = true
@spin_thread = Thread.new do
loop do
@stream.print(colorize(:rainbow, @pinwheel.rotate!.first + "\b"))
sleep(0.1)
@stream.print(colorize(:rainbow, @pinwheel.rotate!.first + "\b"))
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/bolt/executor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ def mock_node_results
executor.round_robin([])
end

it "starts and stops the spinner" do
it "stops the spinner" do
skein = %w[a b c d].each_with_index.map do |val, index|
fiber = Fiber.new do
sleep(rand(0.01..0.1))
Expand All @@ -873,7 +873,7 @@ def mock_node_results
end

executor.round_robin(skein)
expect(collector.events).to include({ type: :start_spin })
expect(collector.events).to include({ type: :stop_spin })
end

it "returns results in the same order they were originally" do
Expand Down

0 comments on commit 0df4785

Please sign in to comment.