mirror of
https://github.com/elastic/logstash.git
synced 2025-04-24 06:37:19 -04:00
PR #17006 revealed that the `VERSION_QUALIFIER` env var gets honored in various scripts when present but empty. This shouldn't be the case as the DRA process is designed to gracefully ignore empty values for this variable. This commit changes various ruby scripts to not treat "" as truthy. Bash scripts (used by CI etc.) are already ok with this as part of refactorings done in #16907. --------- Co-authored-by: Andrea Selva <selva.andre@gmail.com>
197 lines
6 KiB
Ruby
197 lines
6 KiB
Ruby
ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..'))
|
|
$LOAD_PATH.unshift File.join(ROOT, 'logstash-core/lib')
|
|
FIXTURES_DIR = File.expand_path(File.join("..", "..", "fixtures"), __FILE__)
|
|
|
|
require 'logstash/version'
|
|
require 'json'
|
|
require 'stud/try'
|
|
require 'docker-api'
|
|
require_relative '../patches/excon/unix_socket'
|
|
|
|
def version
|
|
@version ||= LOGSTASH_VERSION
|
|
end
|
|
|
|
def qualified_version
|
|
qualifier = ENV['VERSION_QUALIFIER'].to_s.strip.empty? ? nil : ENV['VERSION_QUALIFIER']
|
|
qualified_version = qualifier ? [version, qualifier].join("-") : version
|
|
ENV["RELEASE"] == "1" ? qualified_version : [qualified_version, "SNAPSHOT"].join("-")
|
|
end
|
|
|
|
def find_image(flavor)
|
|
Docker::Image.all.detect {
|
|
|image| image.info['RepoTags'].detect {
|
|
|tag| tag == "docker.elastic.co/logstash/logstash-#{flavor}:#{qualified_version}"
|
|
}}
|
|
end
|
|
|
|
def create_container(image, options = {})
|
|
image.run(nil, options)
|
|
end
|
|
|
|
def start_container(image, options = {})
|
|
container = create_container(image, options)
|
|
wait_for_logstash(container)
|
|
container
|
|
end
|
|
|
|
def wait_for_logstash(container)
|
|
Stud.try(40.times, [NoMethodError, Docker::Error::ConflictError, RSpec::Expectations::ExpectationNotMetError, TypeError]) do
|
|
expect(logstash_available?(container)).to be true
|
|
# unknown or red status may be also meaningful while testing
|
|
expect(%w(unknown green yellow red).include?(get_logstash_status(container))).to be true
|
|
end
|
|
end
|
|
|
|
def wait_for_pipeline(container, pipeline = 'main')
|
|
Stud.try(40.times, [NoMethodError, Docker::Error::ConflictError, RSpec::Expectations::ExpectationNotMetError, TypeError]) do
|
|
expect(pipeline_stats_available?(container, pipeline)).to be true
|
|
end
|
|
end
|
|
|
|
def cleanup_container(container)
|
|
unless container.nil?
|
|
begin
|
|
container.stop
|
|
ensure
|
|
container.delete(:force => true)
|
|
end
|
|
end
|
|
end
|
|
|
|
def license_label_for_flavor(flavor)
|
|
flavor.match(/oss/) ? 'Apache 2.0' : 'Elastic License'
|
|
end
|
|
|
|
def license_agreement_for_flavor(flavor)
|
|
flavor.match(/oss/) ? 'Apache License' : 'ELASTIC LICENSE AGREEMENT!'
|
|
end
|
|
|
|
def get_logstash_status(container)
|
|
make_request(container, 'curl -s http://localhost:9600/')['status']
|
|
end
|
|
|
|
def get_node_info(container)
|
|
make_request(container, 'curl -s http://localhost:9600/_node/')
|
|
end
|
|
|
|
def get_node_stats(container)
|
|
make_request(container, 'curl -s http://localhost:9600/_node/stats')
|
|
end
|
|
|
|
def get_pipeline_setting(container, property, pipeline = 'main')
|
|
make_request(container, "curl -s http://localhost:9600/_node/pipelines/#{pipeline}")
|
|
.dig('pipelines', pipeline, property)
|
|
end
|
|
|
|
def get_pipeline_stats(container, pipeline = 'main')
|
|
make_request(container, "curl -s http://localhost:9600/_node/stats/pipelines").dig('pipelines', pipeline)
|
|
end
|
|
|
|
def get_plugin_info(container, type, id, pipeline = 'main')
|
|
pipeline_info = make_request(container, "curl -s http://localhost:9600/_node/stats/pipelines")
|
|
all_plugins = pipeline_info.dig('pipelines', pipeline, 'plugins', type)
|
|
if all_plugins.nil?
|
|
# This shouldn't happen, so if it does, let's figure out why
|
|
puts container.logs(stdout: true)
|
|
puts "Unable to find plugins from #{pipeline_info}, when looking for #{type} plugins in #{pipeline}"
|
|
return nil
|
|
end
|
|
all_plugins.find {|plugin| plugin['id'] == id}
|
|
end
|
|
|
|
def logstash_available?(container)
|
|
response = exec_in_container_full(container, 'curl -s http://localhost:9600')
|
|
return false if response[:exitcode] != 0
|
|
!(response[:stdout].nil? || response[:stdout].empty?)
|
|
end
|
|
|
|
def pipeline_stats_available?(container, pipeline)
|
|
response = make_request(container, "curl -s http://localhost:9600/_node/stats/pipelines")
|
|
plugins = response.dig('pipelines', pipeline, 'plugins')
|
|
!(plugins.nil? || plugins.empty?)
|
|
end
|
|
|
|
def make_request(container, url)
|
|
JSON.parse(exec_in_container(container, url))
|
|
end
|
|
|
|
def get_settings(container)
|
|
YAML.load(container.read_file('/usr/share/logstash/config/logstash.yml'))
|
|
end
|
|
|
|
def java_process(container)
|
|
ps_output = exec_in_container(container, "ps -o pid,user,group,args")
|
|
java_ps = ps_output.split("\n").find {|process| process.match(/java/) } || ""
|
|
java_ps.match(/^\s+(?<pid>\d+)\s+(?<user>.+?)\s+(?<group>.+?)\s+(?<args>.+?)$/)
|
|
end
|
|
|
|
# Runs the given command in the given container. This method returns
|
|
# a hash including the `stdout` and `stderr` outputs and the exit code
|
|
def exec_in_container_full(container, command)
|
|
response = container.exec(command.split)
|
|
{
|
|
:stdout => response[0],
|
|
:stderr => response[1],
|
|
:exitcode => response[2]
|
|
}
|
|
end
|
|
|
|
# Runs the given command in the given container. This method returns
|
|
# only the stripped/chomped `stdout` output.
|
|
def exec_in_container(container, command)
|
|
exec_in_container_full(container, command)[:stdout].join.chomp.strip
|
|
end
|
|
|
|
def running_architecture
|
|
architecture = ENV['DOCKER_ARCHITECTURE']
|
|
architecture = normalized_architecture(`uname -m`.strip) if architecture.nil?
|
|
architecture
|
|
end
|
|
|
|
def normalized_architecture(cpu)
|
|
case cpu
|
|
when 'x86_64'
|
|
'amd64'
|
|
when 'aarch64'
|
|
'arm64'
|
|
else
|
|
cpu
|
|
end
|
|
end
|
|
|
|
RSpec::Matchers.define :have_correct_license_label do |expected|
|
|
match do |actual|
|
|
values_match? license_label_for_flavor(expected), actual
|
|
end
|
|
failure_message do |actual|
|
|
"expected License:#{actual} to eq #{license_label_for_flavor(expected)}"
|
|
end
|
|
end
|
|
|
|
RSpec::Matchers.define :have_correct_license_agreement do |expected|
|
|
match do |actual|
|
|
values_match? /#{license_agreement_for_flavor(expected)}/, actual
|
|
true
|
|
end
|
|
failure_message do |actual|
|
|
"expected License Agreement:#{actual} to contain #{license_agreement_for_flavor(expected)}"
|
|
end
|
|
end
|
|
|
|
RSpec::Matchers.define :have_correct_architecture do
|
|
match do |actual|
|
|
values_match? running_architecture, actual
|
|
end
|
|
failure_message do |actual|
|
|
"expected Architecture: #{actual} to be #{running_architecture}"
|
|
end
|
|
end
|
|
|
|
shared_context 'image_context' do |flavor|
|
|
before do
|
|
@image = find_image(flavor)
|
|
@image_config = @image.json['Config']
|
|
@labels = @image_config['Labels']
|
|
end
|
|
end
|