logstash/qa/vagrant/command.rb

87 lines
2.5 KiB
Ruby

# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
require "open3"
require "bundler"
module LogStash
class CommandExecutor
class CommandError < StandardError; end
class CommandResponse
attr_reader :stdin, :stdout, :stderr, :exitstatus
def initialize(stdin, stdout, stderr, exitstatus)
@stdin = stdin
@stdout = stdout
@stderr = stderr
@exitstatus = exitstatus
end
def success?
exitstatus == 0
end
end
def self.run(cmd, debug=false)
# This block is require to be able to launch a ruby subprocess
# that use bundler.
Bundler.with_unbundled_env do
stdin, stdout, stderr, wait_thr = Open3.popen3(cmd)
stdout_acc, stderr_acc = "", ""
stdout_reporter = reporter(stdout, wait_thr) do |c|
stdout_acc << c
print c if debug
end
reporter(stderr, wait_thr) do |c|
stderr_acc << c;
print c if debug
end
stdout_reporter.join
CommandResponse.new(stdin, stdout_acc, stderr_acc, wait_thr.value.exitstatus)
end
end
# This method will raise an exception if the `CMD`
# was not run successfully and will display the content of STDERR
def self.run!(cmd, debug=false)
response = run(cmd, debug)
unless response.success?
raise CommandError, "CMD: #{cmd} STDERR: #{response.stderr}"
end
response
end
private
def self.reporter(io, wait_thr, &block)
Thread.new(io, wait_thr) do |_io, _wait_thr|
while (_wait_thr.status == "run")
begin
c = _io.read(1)
block.call(c) if c
rescue IO::WaitReadable
IO.select([_io])
retry
end
end
end
end
end
end