From 73f07fc79984426aeba965b56533c66124dc81b3 Mon Sep 17 00:00:00 2001 From: Ry Biesemeyer Date: Tue, 22 Aug 2023 04:17:06 +0000 Subject: [PATCH 1/2] spike: deprecated settings all working --- Gemfile | 8 + lib/logstash/plugin_mixins/http_client.rb | 326 +++++++++--------- .../deprecated_ssl_config_support.rb | 75 ++++ logstash-mixin-http_client.gemspec | 1 + spec/plugin_mixin/http_client_spec.rb | 42 ++- 5 files changed, 296 insertions(+), 156 deletions(-) create mode 100644 lib/logstash/plugin_mixins/http_client/deprecated_ssl_config_support.rb diff --git a/Gemfile b/Gemfile index 2b03d18..4cf9869 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,11 @@ source 'https://rubygems.org' # Specify your gem's dependencies in logstash-mass_effect.gemspec gemspec + +logstash_path = ENV["LOGSTASH_PATH"] || "../../logstash" +use_logstash_source = ENV["LOGSTASH_SOURCE"] && ENV["LOGSTASH_SOURCE"].to_s == "1" + +if Dir.exist?(logstash_path) && use_logstash_source + gem 'logstash-core', :path => "#{logstash_path}/logstash-core" + gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api" +end \ No newline at end of file diff --git a/lib/logstash/plugin_mixins/http_client.rb b/lib/logstash/plugin_mixins/http_client.rb index 26c1772..d7b76eb 100644 --- a/lib/logstash/plugin_mixins/http_client.rb +++ b/lib/logstash/plugin_mixins/http_client.rb @@ -7,203 +7,219 @@ module LogStash::PluginMixins::HttpClient class InvalidHTTPConfigError < StandardError; end + def self.[](**a) + Adapter.new(**a) + end + def self.included(base) - require 'manticore' - base.extend(self) - base.setup_http_client_config + # TODO: deprecate the act of including this mixin directly, + # in a way that turns focus to plugin maintainers since + # an end-user cannot act to resolve the issue. + base.include(Adapter.new(with_deprecated: true)) end - public - def setup_http_client_config - # Timeout (in seconds) for the entire request - config :request_timeout, :validate => :number, :default => 60 + class Adapter < Module + def initialize(with_deprecated: false) + @include_dep = with_deprecated + end + + def included(base) + base.include(Implementation) + if @include_dep + require_relative 'http_client/deprecated_ssl_config_support' + base.include(DeprecatedSslConfigSupport) + end + nil + end + end + private_constant :Adapter - # Timeout (in seconds) to wait for data on the socket. Default is `10s` - config :socket_timeout, :validate => :number, :default => 10 + module Implementation + def self.included(base) + require 'manticore' - # Timeout (in seconds) to wait for a connection to be established. Default is `10s` - config :connect_timeout, :validate => :number, :default => 10 + # Timeout (in seconds) for the entire request + base.config :request_timeout, :validate => :number, :default => 60 - # Should redirects be followed? Defaults to `true` - config :follow_redirects, :validate => :boolean, :default => true + # Timeout (in seconds) to wait for data on the socket. Default is `10s` + base.config :socket_timeout, :validate => :number, :default => 10 - # Max number of concurrent connections. Defaults to `50` - config :pool_max, :validate => :number, :default => 50 + # Timeout (in seconds) to wait for a connection to be established. Default is `10s` + base.config :connect_timeout, :validate => :number, :default => 10 - # Max number of concurrent connections to a single host. Defaults to `25` - config :pool_max_per_route, :validate => :number, :default => 25 + # Should redirects be followed? Defaults to `true` + base.config :follow_redirects, :validate => :boolean, :default => true - # Turn this on to enable HTTP keepalive support. We highly recommend setting `automatic_retries` to at least - # one with this to fix interactions with broken keepalive implementations. - config :keepalive, :validate => :boolean, :default => true + # Max number of concurrent connections. Defaults to `50` + base.config :pool_max, :validate => :number, :default => 50 - # How many times should the client retry a failing URL. We highly recommend NOT setting this value - # to zero if keepalive is enabled. Some servers incorrectly end keepalives early requiring a retry! - # Note: if `retry_non_idempotent` is set only GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried. - config :automatic_retries, :validate => :number, :default => 1 + # Max number of concurrent connections to a single host. Defaults to `25` + base.config :pool_max_per_route, :validate => :number, :default => 25 - # If `automatic_retries` is enabled this will cause non-idempotent HTTP verbs (such as POST) to be retried. - config :retry_non_idempotent, :validate => :boolean, :default => false + # Turn this on to enable HTTP keepalive support. We highly recommend setting `automatic_retries` to at least + # one with this to fix interactions with broken keepalive implementations. + base.config :keepalive, :validate => :boolean, :default => true - # How long to wait before checking if the connection is stale before executing a request on a connection using keepalive. - # # You may want to set this lower, possibly to 0 if you get connection errors regularly - # Quoting the Apache commons docs (this client is based Apache Commmons): - # 'Defines period of inactivity in milliseconds after which persistent connections must be re-validated prior to being leased to the consumer. Non-positive value passed to this method disables connection validation. This check helps detect connections that have become stale (half-closed) while kept inactive in the pool.' - # See https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html#setValidateAfterInactivity(int)[these docs for more info] - config :validate_after_inactivity, :validate => :number, :default => 200 + # How many times should the client retry a failing URL. We highly recommend NOT setting this value + # to zero if keepalive is enabled. Some servers incorrectly end keepalives early requiring a retry! + # Note: if `retry_non_idempotent` is set only GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried. + base.config :automatic_retries, :validate => :number, :default => 1 - # If you need to use a custom X.509 CA (.pem certs) specify the path to that here - config :cacert, :validate => :path + # If `automatic_retries` is enabled this will cause non-idempotent HTTP verbs (such as POST) to be retried. + base.config :retry_non_idempotent, :validate => :boolean, :default => false - # If you'd like to use a client certificate (note, most people don't want this) set the path to the x509 cert here - config :client_cert, :validate => :path - # If you're using a client certificate specify the path to the encryption key here - config :client_key, :validate => :path + # How long to wait before checking if the connection is stale before executing a request on a connection using keepalive. + # # You may want to set this lower, possibly to 0 if you get connection errors regularly + # Quoting the Apache commons docs (this client is based Apache Commmons): + # 'Defines period of inactivity in milliseconds after which persistent connections must be re-validated prior to being leased to the consumer. Non-positive value passed to this method disables connection validation. This check helps detect connections that have become stale (half-closed) while kept inactive in the pool.' + # See https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html#setValidateAfterInactivity(int)[these docs for more info] + base.config :validate_after_inactivity, :validate => :number, :default => 200 - # If you need to use a custom keystore (`.jks`) specify that here. This does not work with .pem keys! - config :keystore, :validate => :path + # If you need to use a custom X.509 CA (.pem certs) specify the path to that here + base.config :ssl_certificate_authorities, :validate => :path, :list => :true - # Specify the keystore password here. - # Note, most .jks files created with keytool require a password! - config :keystore_password, :validate => :password + # If you'd like to use a client certificate (note, most people don't want this) set the path to the x509 cert here + base.config :ssl_certificate, :validate => :path + # If you're using a client certificate specify the path to the encryption key here + base.config :ssl_key, :validate => :path - # Specify the keystore type here. One of `JKS` or `PKCS12`. Default is `JKS` - config :keystore_type, :validate => :string, :default => "JKS" + # If you need to use a custom keystore (`.jks`) specify that here. This does not work with .pem keys! + base.config :ssl_keystore_path, :validate => :path - # Naming aligned with the Elastic stack. - # full: verifies that the provided certificate is signed by a trusted authority (CA) and also verifies that the - # server’s hostname (or IP address) matches the names identified within the certificate - # none: no verification of the server’s certificate - config :ssl_verification_mode, :validate => ['full', 'none'], :default => 'full' + # Specify the keystore password here. + # Note, most .jks files created with keytool require a password! + base.config :ssl_keystore_password, :validate => :password - # NOTE: the default setting [] uses Java SSL engine defaults. - config :ssl_supported_protocols, :validate => ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], :default => [], :list => true + # Specify the keystore type here. One of `JKS` or `PKCS12`. Default is `JKS` + base.config :ssl_keystore_type, :validate => %w(pkcs12 jks), :default => "jks" - # If you need to use a custom truststore (`.jks`) specify that here. This does not work with .pem certs! - config :truststore, :validate => :path + # Naming aligned with the Elastic stack. + # full: verifies that the provided certificate is signed by a trusted authority (CA) and also verifies that the + # server’s hostname (or IP address) matches the names identified within the certificate + # none: no verification of the server’s certificate + base.config :ssl_verification_mode, :validate => ['full', 'none'], :default => 'full' - # Specify the truststore password here. - # Note, most .jks files created with keytool require a password! - config :truststore_password, :validate => :password + # NOTE: the default setting [] uses Java SSL engine defaults. + base.config :ssl_supported_protocols, :validate => ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], :default => [], :list => true - # Specify the truststore type here. One of `JKS` or `PKCS12`. Default is `JKS` - config :truststore_type, :validate => :string, :default => "JKS" + # If you need to use a custom truststore (`.jks`) specify that here. This does not work with .pem certs! + base.config :ssl_truststore_path, :validate => :path - # Enable cookie support. With this enabled the client will persist cookies - # across requests as a normal web browser would. Enabled by default - config :cookies, :validate => :boolean, :default => true + # Specify the truststore password here. + # Note, most .jks files created with keytool require a password! + base.config :ssl_truststore_password, :validate => :password - # If you'd like to use an HTTP proxy . This supports multiple configuration syntaxes: - # - # 1. Proxy host in form: `http://proxy.org:1234` - # 2. Proxy host in form: `{host => "proxy.org", port => 80, scheme => 'http', user => 'username@host', password => 'password'}` - # 3. Proxy host in form: `{url => 'http://proxy.org:1234', user => 'username@host', password => 'password'}` - config :proxy + # Specify the truststore type here. One of `JKS` or `PKCS12`. Default is `JKS` + base.config :ssl_truststore_type, :validate => %w(pkcs12 jks), :default => "jks" - # Username to use for HTTP auth. - config :user, :validate => :string + # Enable cookie support. With this enabled the client will persist cookies + # across requests as a normal web browser would. Enabled by default + base.config :cookies, :validate => :boolean, :default => true - # Password to use for HTTP auth - config :password, :validate => :password - end + # If you'd like to use an HTTP proxy . This supports multiple configuration syntaxes: + # + # 1. Proxy host in form: `http://proxy.org:1234` + # 2. Proxy host in form: `{host => "proxy.org", port => 80, scheme => 'http', user => 'username@host', password => 'password'}` + # 3. Proxy host in form: `{url => 'http://proxy.org:1234', user => 'username@host', password => 'password'}` + base.config :proxy + + # Username to use for HTTP auth. + base.config :user, :validate => :string - public - def client_config - c = { - connect_timeout: @connect_timeout, - socket_timeout: @socket_timeout, - request_timeout: @request_timeout, - follow_redirects: @follow_redirects, - automatic_retries: @automatic_retries, - retry_non_idempotent: @retry_non_idempotent, - check_connection_timeout: @validate_after_inactivity, - pool_max: @pool_max, - pool_max_per_route: @pool_max_per_route, - cookies: @cookies, - keepalive: @keepalive - } - - if @proxy - # Symbolize keys if necessary - c[:proxy] = @proxy.is_a?(Hash) ? - @proxy.reduce({}) {|memo,(k,v)| memo[k.to_sym] = v; memo} : - @proxy + # Password to use for HTTP auth + base.config :password, :validate => :password end - if @user - if !@password || !@password.value - raise ::LogStash::ConfigurationError, "User '#{@user}' specified without password!" + public + + def client_config + c = { + connect_timeout: @connect_timeout, + socket_timeout: @socket_timeout, + request_timeout: @request_timeout, + follow_redirects: @follow_redirects, + automatic_retries: @automatic_retries, + retry_non_idempotent: @retry_non_idempotent, + check_connection_timeout: @validate_after_inactivity, + pool_max: @pool_max, + pool_max_per_route: @pool_max_per_route, + cookies: @cookies, + keepalive: @keepalive + } + + if @proxy + # Symbolize keys if necessary + c[:proxy] = @proxy.is_a?(Hash) ? + @proxy.reduce({}) {|memo,(k,v)| memo[k.to_sym] = v; memo} : + @proxy end - # Symbolize keys if necessary - c[:auth] = { - :user => @user, - :password => @password.value, - :eager => true - } - end + if @user + if !@password || !@password.value + raise ::LogStash::ConfigurationError, "User '#{@user}' specified without password!" + end + + # Symbolize keys if necessary + c[:auth] = { + :user => @user, + :password => @password.value, + :eager => true + } + end + + c[:ssl] = ssl_options - c[:ssl] = {} - if @cacert - c[:ssl][:ca_file] = @cacert + c end - if @truststore - c[:ssl].merge!( - :truststore => @truststore, - :truststore_type => @truststore_type, - :truststore_password => @truststore_password.value - ) - - if c[:ssl][:truststore_password].nil? - raise LogStash::ConfigurationError, "Truststore declared without a password! This is not valid, please set the 'truststore_password' option" + private + + def ssl_options + + options = {} + if @ssl_certificate_authorities&.any? + raise LogStash::ConfigurationError, 'Multiple values on `ssl_certificate_authorities` are not supported by this plugin' if @ssl_certificate_authorities.size > 1 + + options[:ca_file] = @ssl_certificate_authorities.first end - end - if @keystore - c[:ssl].merge!( - :keystore => @keystore, - :keystore_type => @keystore_type, - :keystore_password => @keystore_password.value - ) + if @ssl_truststore_path + options[:truststore] = @ssl_truststore_path + options[:truststore_type] = @ssl_truststore_type if @ssl_truststore_type + options[:truststore_password] = @ssl_truststore_password.value if @ssl_truststore_password + elsif @ssl_truststore_password + fail LogStash::ConfigurationError, "truststore_password requires ssl_truststore_path you fool" + end - if c[:ssl][:keystore_password].nil? - raise LogStash::ConfigurationError, "Keystore declared without a password! This is not valid, please set the 'keystore_password' option" + if @ssl_keystore_path + options[:keystore] = @ssl_keystore_path + options[:keystore_type] = @ssl_keystore_type if @ssl_keystore_type + options[:keystore_password] = @ssl_keystore_password.value if @ssl_keystore_password + elsif @ssl_keystore_password + fail LogStash::ConfigurationError, "ssl_keystore_password requires ssl_keystore_path you fool" end - end - if @client_cert && @client_key - c[:ssl][:client_cert] = @client_cert - c[:ssl][:client_key] = @client_key - elsif !!@client_cert ^ !!@client_key - raise InvalidHTTPConfigError, "You must specify both client_cert and client_key for an HTTP client, or neither!" - end + if @ssl_certificate && @ssl_key + options[:client_cert] = @ssl_certificate + options[:client_key] = @ssl_key + elsif !!@ssl_certificate ^ !!@ssl_key + raise InvalidHTTPConfigError, "You must specify both `ssl_certificate` and `ssl_key` for an HTTP client, or neither!" + end - case @ssl_verification_mode - when 'full' - # NOTE: would make sense to have :browser here but historically we've used the (:strict) default - # - # supporting `ssl_verification_mode => strict` the same way ES does might require upstream Manticore - # changes -> as in ES/Beats setting `strict` means: "if the SAN is empty return an error" - c[:ssl][:verify] = :strict # :default - when 'none' - c[:ssl][:verify] = :disable - end + options[:verify] = @ssl_verification_mode == 'full' ? :strict : :disable + options[:protocols] = @ssl_supported_protocols if @ssl_supported_protocols&.any? + options[:cipher_suites] = @ssl_cipher_suites if @ssl_cipher_suites&.any? - if @ssl_supported_protocols && @ssl_supported_protocols.any? - c[:ssl][:protocols] = @ssl_supported_protocols + options end - c - end - - private - def make_client - Manticore::Client.new(client_config) - end + def make_client + Manticore::Client.new(client_config) + end - public - def client - @client ||= make_client + public + def client + @client ||= make_client + end end -end +end \ No newline at end of file diff --git a/lib/logstash/plugin_mixins/http_client/deprecated_ssl_config_support.rb b/lib/logstash/plugin_mixins/http_client/deprecated_ssl_config_support.rb new file mode 100644 index 0000000..ab7f2c1 --- /dev/null +++ b/lib/logstash/plugin_mixins/http_client/deprecated_ssl_config_support.rb @@ -0,0 +1,75 @@ +module LogStash::PluginMixins::HttpClient + module DeprecatedSslConfigSupport + def self.included(base) + fail ArgumentError unless base <= LogStash::PluginMixins::HttpClient::Implementation + + require 'logstash/plugin_mixins/normalize_config_support' + base.include(LogStash::PluginMixins::NormalizeConfigSupport) + + # If you need to use a custom X.509 CA (.pem certs) specify the path to that here + base.config :cacert, :validate => :path, :deprecated => 'Use `ssl_certificate_authorities` instead' + # If you'd like to use a client certificate (note, most people don't want this) set the path to the x509 cert here + base.config :client_cert, :validate => :path, :deprecated => 'Use `ssl_certificate` instead' + # If you're using a client certificate specify the path to the encryption key here + base.config :client_key, :validate => :path, :deprecated => 'Use `ssl_key` instead' + # If you need to use a custom keystore (`.jks`) specify that here. This does not work with .pem keys! + base.config :keystore, :validate => :path, :deprecated => 'Use `ssl_keystore_path` instead' + # Specify the keystore password here. + # Note, most .jks files created with keytool require a password! + base.config :keystore_password, :validate => :password, :deprecated => 'Use `ssl_keystore_password` instead' + # Specify the keystore type here. One of `JKS` or `PKCS12`. Default is `JKS` + base.config :keystore_type, :validate => :string, :default => 'JKS', :deprecated => 'Use `ssl_keystore_type` instead' + # If you need to use a custom truststore (`.jks`) specify that here. This does not work with .pem certs! + base.config :truststore, :validate => :path, :deprecated => 'Use `ssl_truststore_path` instead' + # Specify the truststore password here. + # Note, most .jks files created with keytool require a password! + base.config :truststore_password, :validate => :password, :deprecated => 'Use `ssl_truststore_password` instead' + # Specify the truststore type here. One of `JKS` or `PKCS12`. Default is `JKS` + base.config :truststore_type, :validate => :string, :default => 'JKS', :deprecated => 'Use `ssl_truststore_type` instead' + # NOTE: the default setting [] uses Java SSL engine defaults. + end + + def initialize(*a) + super + + @ssl_certificate_authorities = normalize_config(:ssl_certificate_authorities) do |normalize| + normalize.with_deprecated_mapping(:cacert) do |cacert| + [cacert] + end + end + + @ssl_certificate = normalize_config(:ssl_certificate) do |normalize| + normalize.with_deprecated_alias(:client_cert) + end + + @ssl_key = normalize_config(:ssl_key) do |normalize| + normalize.with_deprecated_alias(:client_key) + end + + %w[keystore truststore].each do |store| + %w[path type password].each do |variable| + config_name = "ssl_#{store}_#{variable}" + normalized_value = normalize_config(config_name) do |normalize| + deprecated_config_alias = variable == 'path' ? store : "#{store}_#{variable}" + normalize.with_deprecated_alias(deprecated_config_alias.to_sym) + end + instance_variable_set("@#{config_name}", normalized_value) + params[config_name.to_s] = normalized_value unless normalized_value.nil? + end + end + end + + def ssl_options + fail(InvalidHTTPConfigError, "When `client_cert` is provided, `client_key` must also be provided") if @client_cert && !@client_key + fail(InvalidHTTPConfigError, "A `client_key` is not allowed unless a `client_cert` is provided") if @client_key && !@client_cert + + fail(LogStash::ConfigurationError, "When `keystore` is provided, `keystore_password` must also be provided") if @keystore && !@keystore_password + fail(LogStash::ConfigurationError, "A `keystore_password` is not allowed unless a `keystore` is provided") if @keystore_password && !@keystore + + fail(LogStash::ConfigurationError, "When `truststore` is provided, `truststore_password` must also be provided") if @truststore && !@truststore_password + fail(LogStash::ConfigurationError, "A `truststore_password` is not allowed unless a `truststore` is provided") if @truststore_password && !@truststore + + super + end + end +end \ No newline at end of file diff --git a/logstash-mixin-http_client.gemspec b/logstash-mixin-http_client.gemspec index 6f7f04e..04d242d 100644 --- a/logstash-mixin-http_client.gemspec +++ b/logstash-mixin-http_client.gemspec @@ -19,6 +19,7 @@ Gem::Specification.new do |s| s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99" s.add_runtime_dependency 'logstash-codec-plain' s.add_runtime_dependency 'manticore', '>= 0.8.0', '< 1.0.0' + s.add_runtime_dependency 'logstash-mixin-normalize_config_support', '~>1.0' s.add_development_dependency 'logstash-devutils' s.add_development_dependency 'stud' diff --git a/spec/plugin_mixin/http_client_spec.rb b/spec/plugin_mixin/http_client_spec.rb index 9dc4eb3..13fdd89 100644 --- a/spec/plugin_mixin/http_client_spec.rb +++ b/spec/plugin_mixin/http_client_spec.rb @@ -5,6 +5,7 @@ class Dummy < LogStash::Inputs::Base include LogStash::PluginMixins::HttpClient + config_name 'dummy' end describe LogStash::PluginMixins::HttpClient do @@ -50,6 +51,26 @@ class Dummy < LogStash::Inputs::Base end end + shared_examples 'a deprecated setting with guidance' do |deprecations_and_guidance| + + let(:logger_stub) { double('Logger').as_null_object } + + before(:each) do + allow(Dummy).to receive(:logger).and_return(logger_stub) + end + + deprecations_and_guidance.each do |deprecated_setting_name, canonical_setting_name| + it "emits a warning about the setting `#{deprecated_setting_name}` being deprecated and provides guidance to use `#{canonical_setting_name}`" do + Dummy.new(conf) + + deprecation_text = "deprecated config setting \"#{deprecated_setting_name}\" set" + guidance_text = "Use `#{canonical_setting_name}` instead" + + expect(logger_stub).to have_received(:warn).with(a_string_including(deprecation_text).and(including(guidance_text)), anything) + end + end + end + describe "with a custom ssl bundle" do let(:file) { Stud::Temporary.file } let(:path) { file.path } @@ -59,6 +80,9 @@ class Dummy < LogStash::Inputs::Base let(:conf) { basic_config.merge("cacert" => path) } include_examples("setting ca bundles", :ca_file) + + it_behaves_like('a deprecated setting with guidance', + 'cacert' => 'ssl_certificate_authorities') end context "with JKS" do @@ -71,6 +95,11 @@ class Dummy < LogStash::Inputs::Base } include_examples("setting ca bundles", :truststore, :jks) + + it_behaves_like('a deprecated setting with guidance', + 'truststore' => 'ssl_truststore_path', + 'truststore_password' => 'ssl_truststore_password', + 'truststore_type' => 'ssl_truststore_type') end end @@ -133,11 +162,18 @@ class Dummy < LogStash::Inputs::Base store => path, "#{store}_password" => password, "#{store}_type" => "jks" - ) + ).compact } include_examples("setting ca bundles", store.to_sym, :jks) + + + it_behaves_like('a deprecated setting with guidance', + "#{store}" => "ssl_#{store}_path", + "#{store}_password" => "ssl_#{store}_password", + "#{store}_type" => "ssl_#{store}_type") + context "with no password set" do let(:password) { nil } @@ -163,6 +199,10 @@ class Dummy < LogStash::Inputs::Base Dummy.new(conf).client_config }.not_to raise_error end + + it_behaves_like('a deprecated setting with guidance', + 'client_cert' => 'ssl_certificate', + 'client_key' => 'ssl_key') end shared_examples("raising a configuration error") do From d3bdbe3fb33502f4255ba939abed36bea07c4bde Mon Sep 17 00:00:00 2001 From: Ry Biesemeyer Date: Tue, 22 Aug 2023 18:58:54 +0000 Subject: [PATCH 2/2] use modern shared travis config --- .travis.yml | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e328f6..074287d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,3 @@ --- -sudo: false -language: ruby -cache: bundler - -script: bundle exec rspec spec -jdk: openjdk8 -matrix: - include: - - rvm: jruby-9.2.20.1 - env: LOGSTASH_BRANCH=8.0 - - rvm: jruby-9.2.20.1 - env: LOGSTASH_BRANCH=7.16 - - rvm: jruby-9.1.13.0 - env: LOGSTASH_BRANCH=6.7 - - rvm: jruby-9.2.7.0 - env: LOGSTASH_BRANCH=6.8 - fast_finish: true -before_install: gem install bundler -v '< 2' +import: + - logstash-plugins/.ci:travis/travis.yml@1.x \ No newline at end of file