elastic / logstash

Logstash - transport and process your logs, events, or other data
https://www.elastic.co/products/logstash
Other
14.18k stars 3.49k forks source link

Using pre-release gems in a Gemfile break update flow. #4955

Open ph opened 8 years ago

ph commented 8 years ago

Discovered when testing PR #4941.

When you are using a pre-release gems in the Gemfile it breaks the plugin update all flow.

#Gemfile
gem "logstash-input-kafka", "3.0.0.beta4"
~/e/logstash git:pr/4941 ❯❯❯ bin/logstash-plugin update                                                                                                                                                   ⏎ ✱
ERROR: Updated Aborted, message: undefined method `version' for nil:NilClass
~/e/logstash git:pr/4941 ❯❯❯

This is strange I have tried the following in the 5.0 branch which should do the same result. Add this line to the Gemfile:

gem "logstash-input-beats", "2.2.3"

And if you do this:

bin/plugin install --no-verify

Theses commands successfully update the current packages, so the problem I think is only related to the pre-release version of the gem.

ph commented 8 years ago

stacktrace

nly -J-XX:+HeapDumpOnOutOfMemoryError -J-Xmx1g -J-XX:HeapDumpPath=/Users/ph/es/logstash/heapdump.hprof /Users/ph/es/logstash/lib/pluginmanager/main.rb update
NoMethodError: undefined method `version' for nil:NilClass
  update_to_major_version? at /Users/ph/es/logstash/lib/pluginmanager/util.rb:67
         validates_version at /Users/ph/es/logstash/lib/pluginmanager/update.rb:75
              update_gems! at /Users/ph/es/logstash/lib/pluginmanager/update.rb:50
                    select at org/jruby/RubyArray.java:2470
              update_gems! at /Users/ph/es/logstash/lib/pluginmanager/update.rb:47
                   execute at /Users/ph/es/logstash/lib/pluginmanager/update.rb:26
                       run at /Users/ph/es/logstash/vendor/bundle/jruby/1.9/gems/clamp-0.6.5/lib/clamp/command.rb:67
                   execute at /Users/ph/es/logstash/vendor/bundle/jruby/1.9/gems/clamp-0.6.5/lib/clamp/subcommand/execution.rb:11
                       run at /Users/ph/es/logstash/vendor/bundle/jruby/1.9/gems/clamp-0.6.5/lib/clamp/command.rb:67
                       run at /Users/ph/es/logstash/vendor/bundle/jruby/1.9/gems/clamp-0.6.5/lib/clamp/command.rb:132
                    (root) at /Users/ph/es/logstash/lib/pluginmanager/main.rb:41
ph commented 8 years ago

The problem is with the Gem::Specification.find_by_name(plugin_name) method by default it will search the gems that match the following requirements Gem::Requirement.new([">= 0"]), this constrains exclude all the locally installed pre-release/beta gems and make the update fails.

See the following code:

[4] pry(LogStash::PluginManager)> Gem::Specification.find_by_name(plugin_name)
=> nil

When we change the local constrains to include pre-release gems we are able to find the local specification.

[5] pry(LogStash::PluginManager)> Gem::Specification.find_by_name(plugin_name,  Gem::Requirement.new([">= 0.b"])
[5] pry(LogStash::PluginManager)* )
=> Gem::Specification.new do |s|
  s.name = "logstash-input-kafka"
  s.version = Gem::Version.new("3.0.0.beta4")
  s.installed_by_version = Gem::Version.new("2.4.8")
  s.authors = ["Elasticsearch"]
  s.date = Time.utc(2016, 3, 31)
  s.dependencies = [Gem::Dependency.new("logstash-core-plugin-api", Gem::Requirement.new(["~> 1.0"]), :runtime),
   Gem::Dependency.new("logstash-codec-json", Gem::Requirement.new([">= 0"]), :runtime),
   Gem::Dependency.new("logstash-codec-plain", Gem::Requirement.new([">= 0"]), :runtime),
   Gem::Dependency.new("stud", Gem::Requirement.new(["< 0.1.0", ">= 0.0.22"]), :runtime),
   Gem::Dependency.new("logstash-devutils", Gem::Requirement.new([">= 0"]), :development)]
  s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
  s.email = "info@elastic.co"
  s.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
  s.licenses = ["Apache License (2.0)"]
  s.metadata = {"group"=>"input", "logstash_plugin"=>"true"}
  s.require_paths = ["lib"]
  s.required_rubygems_version = Gem::Requirement.new(["> 1.3.1"])
  s.rubygems_version = "2.4.8"
  s.specification_version = 4
  s.summary = "This input will read events from a Kafka topic. It uses the high level consumer API provided by Kafka to read messages from the broker"
  end