Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bin/logstash-plugin prepare-offline-pack, improvements to install a pack and rats tests. #6404

Closed
wants to merge 1 commit into from

Conversation

ph
Copy link
Contributor

@ph ph commented Dec 13, 2016

This new command replace the old workflow of pack, unpack and the install --local, and wrap all the logic into one uniform way of installing plugins.
The work is based on the flow developed for installing an x-pack inside Logstash, when you call prepare-offline-pack, the specified plugins and their dependencies will be packaged in a zip.
And this zip can be installed with the same flow as the pack.

Definition:

Source Logstash: Where you run the prepare-offline-pack.
Target Logstash: Where you install the offline package.

PROS:

  • If you install a .gem in the source logstash, the .gem and his dependencies will be bundled.
  • The install flow doesn't need to have access to the internet.
  • Nothing special need to be setup in the target logstash environment.

CONS:

  • The is one minor drawback, the plugins need to have their JARS bundled with them for this flow to work, this is currently the case for all the official plugins.
  • The source Logstash need to have access to the internet when you install plugins before packaging them.

Usage examples:
bin/logstash-plugin prepare-offline-pack logstash-input-beats
bin/logstash-plugin prepare-offline-pack logstash-filter-jdbc logstash-input-beats
bin/logstash-plugin prepare-offline-pack logstash-filter-*
bin/logstash-plugin prepare-offline-pack logstash-filter-* logstash-input-beats

How to install:
bin/logstash-plugin install file:///tmp/logstash-offline-plugins-XXXX.zip

Merge TODO:

  • Remove the travis hack for paquet
  • merge pr
  • Release paquet

Fixes: #6393 #5906

@ph
Copy link
Contributor Author

ph commented Dec 13, 2016

@jsvd you can try it out I've tested the following:

  • I've made an artifact that include paquet
  • I've removed the ~/.m2 directory
  • I've turn off my internet and I have installed the pack
✘ ⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT mkdir tools/                                                                                                                                                                                                                                                             ⏎
⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT cp -r ~/es/logstash/tools/paquet tools/
⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT bin/logstash-plugin list --verbose dissect
ERROR: No plugins found
✘ ⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT rm -rf ~/.m2                                                                                                                                                                                                                                                             ⏎
⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT ping rubygems
ping: cannot resolve rubygems: Unknown host
✘ ⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT bin/logstash-plugin install file:///Users/ph/es/logstash/logstash-offline-plugins-6.0.0-alpha1.zip                                                                                                                                                                       ⏎
Installing file: /Users/ph/es/logstash/logstash-offline-plugins-6.0.0-alpha1.zip

Install successful
⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT
⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT bin/logstash-plugin list --verbose dissect
logstash-filter-dissect (1.0.8)
⚙ph@sashimi/tmp/logstash-6.0.0-alpha1-SNAPSHOT

@ph
Copy link
Contributor Author

ph commented Dec 13, 2016

I've fixed the issue with wildcards you can now do this.

bin/logstash-plugin prepare-offline-pack logstash-filter-* (you might need to quote the name)

Also the install will now work if the plugin is already in the gemfile, it will get update with the right requirements and installed.

@ph ph force-pushed the feature/prepare-offline branch 2 times, most recently from 433e03c to 6a8f88c Compare December 20, 2016 16:39
@ph ph changed the title [WIP] prepare-offline-pack method Prepare-offline-pack method Dec 20, 2016
@ph
Copy link
Contributor Author

ph commented Dec 20, 2016

@jsvd this PR need some review love, will check if travis is green for the integration test.

@ph ph added the v5.2.0 label Dec 20, 2016
@ph
Copy link
Contributor Author

ph commented Dec 20, 2016

@suyograo @jsvd some quirks were also fixed for the install a pack so this need to go in for 5.2

@ph ph changed the title Prepare-offline-pack method bin/logstash-plugin prepare-offline-pack, improvements to install a pack and rats tests. Dec 20, 2016
@ph ph requested a review from suyograo December 20, 2016 16:49
mkdir tools
cp -r ../../tools/paquet tools/
cd ..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we publish the new paquet we can remove this.

mkdir tools
cp -r ../../tools/paquet tools/
cd ..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we publish the new paquet we can remove this.

@ph
Copy link
Contributor Author

ph commented Dec 22, 2016

@jordansissel I confirm that your seccomp tricks does wonder, this PR now uses it for installing a pre-generated pack without any internet access.

Copy link
Member

@jsvd jsvd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall strategy looks good, most of the comments are cosmetic.
I need to test this manually now

definition.lock(lockfile_path)

return @new_deps
gemfile = LogStash::Gemfile.new(File.new(gemfile_path, "r+")).load
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should a pointer for this FD be kept so it is closed on the ensure block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is taken care by LogStash::Gemfile#save and LogStash::Gemfile#restore! that we call in the rescue block.

@@ -20,7 +22,6 @@ def self.inject!(new_deps, options = { :gemfile => LogStash::Environment::GEMFIL
injector.inject(gemfile, lockfile)
end


# This class is pretty similar to what bundler's injector class is doing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're doing different things, compared to the original implementation of the inject method, so this comment should be updated

@@ -35,4 +35,8 @@ def relative_path(path)
require "pathname"
::Pathname.new(path).relative_path_from(::Pathname.new(LogStash::Environment::LOGSTASH_HOME)).to_s
end

def debug?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

# │   └── stud-0.0.22.gem
#
# Right now this work fine, but I think we could also use Bundler's SourceList classes to handle the same thing
def update_in_memory_index(local_source)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what's your preference, but since this is a very destructive method we could name it update_in_memory_index!
(only a suggestion)

end

def self.transform_pattern_into_re(pattern)
Regexp.new(/^#{pattern.gsub(WILDCARD, WILDCARD_INTO_RE)}$/)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're creating the regexp twice here, I suggest instead:

Regexp.new("^#{pattern.gsub(WILDCARD, WILDCARD_INTO_RE)}$")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, will tiddy this up.

)

INVALID_PLUGINS_TO_EXPLICIT_PACK = IGNORE_GEMS_IN_PACK.collect { |name| Regexp.new(/^#{name}/) } + [
/mixin/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you can't pack gems if they depend on mixins? or the pack will be broken because it doesn't include the mixin?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah..I think I understand, this list is used only to check the list of plugins manually stated with pack "plugin", right?

Copy link
Contributor Author

@ph ph Dec 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second comment, forbid plugins declared with the pack command.

def validate_plugins!
@plugins_to_package.each do |plugin_name|
if INVALID_PLUGINS_TO_EXPLICIT_PACK.any? { |invalid_name| plugin_name =~ invalid_name }
raise UnpackablePluginError, "Cannot explicitely pack `#{plugin_name}` for offline installation"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"explicitly", same in method explicitely_declared_plugins_specs below


def explicitely_declared_plugins_specs
@plugins_to_package.collect do |plugin_pattern|
specs = SpecificationHelpers.find_by_name_with_wildcards(plugin_pattern)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of supporting wildcards here? I think it's safer to support only 1 to 1 declaration of plugins to be packed. this would mean that specs.size has to be 1. If it's 2 or more it should generate some exception because you can have multiple plugin specs for different versions (it's easy for vendor/ to become littered with gem trash)

Copy link
Contributor Author

@ph ph Dec 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its was mostly for convenience if someone want to pack all the filters without specifying all of them or all of the elasticsearch related plugins

If it's 2 or more it should generate some exception because you can have multiple plugin specs for different versions (it's easy for vendor/ to become littered with gem trash)

No this is impossible, because when you query the specification cache it can only return what is activated in your lock file, so only 1 version for 1 plugin will be returned.

prepare_package(explicit_plugins_specs, temp_path)
LogStash::Util::Zip.compress(temp_path, @target)
ensure
FileUtils.rm_rf(temp_path) if Dir.exist?(temp_path)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe rm_rf tolerates the absence of the argument like rm -rf path does

# We need to start bundler, dependencies so the plugins are available for the prepare
LogStash::Bundler.setup!({:without => [:build, :development]})

# lazy require paquet since its an external dependency
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/lazy/manually ?

@jsvd
Copy link
Member

jsvd commented Dec 23, 2016

not sure if it is known, but currently running rake artifact:tar creates a broken artifact:

/tmp/logstash-6.0.0-alpha1-SNAPSHOT % bin/logstash -e ""
Bundler::PathError: The path `/tmp/logstash-6.0.0-alpha1-SNAPSHOT/tools/paquet` does not exist.
        load_spec_files at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/source/path.rb:162
            local_specs at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/source/path.rb:92
                  specs at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/source/path.rb:100
  converge_locked_specs at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/definition.rb:539
                   each at org/jruby/RubyArray.java:1613
                   each at /private/tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/jruby/lib/ruby/1.9/forwardable.rb:201
  converge_locked_specs at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/definition.rb:526
                resolve at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/definition.rb:187
                  specs at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/definition.rb:132
              specs_for at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/definition.rb:177
        requested_specs at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/definition.rb:166
        requested_specs at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/environment.rb:18
                  setup at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/runtime.rb:13
                  setup at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler.rb:122
                 setup! at /private/tmp/logstash-6.0.0-alpha1-SNAPSHOT/lib/bootstrap/bundler.rb:64
                 (root) at /tmp/logstash-6.0.0-alpha1-SNAPSHOT/lib/bootstrap/environment.rb:67

@ph
Copy link
Contributor Author

ph commented Dec 23, 2016

The artifact problems is know, I am copying the directory in the suite to make it run, see my comment on https://github.com/elastic/logstash/pull/6404/files#diff-9ea1854b834b68d347a8d758eda73309R25

bin/logstash-plugin prepare-offline-pack logstash-filter-*
bin/logstash-plugin prepare-offline-pack logstash-filter-* logstash-input-beats

You can get a list of the installed plugin run `bin/logstash-plugin list`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/run/by running

@jsvd
Copy link
Member

jsvd commented Dec 23, 2016

offline installation of a packed plugin worked correctly (I had to cp paquet to tools/, like instructed).

I confirm that direct .gem offline installation doesn't work, neither with full path or with a file:/// uri

so, in conclusion: great work @ph, packing for offline and installation works perfectly 👍

@ph ph force-pushed the feature/prepare-offline branch from 83ba528 to abb869c Compare December 23, 2016 21:41
@ph
Copy link
Contributor Author

ph commented Dec 23, 2016

I have finished the reviews changes @jsvd @suyograo

@ph ph force-pushed the feature/prepare-offline branch from abb869c to 02344aa Compare December 29, 2016 16:10
@ph
Copy link
Contributor Author

ph commented Dec 29, 2016

I've rebased this branch and also fixed the problem with the remove plugin test

@jsvd
Copy link
Member

jsvd commented Dec 29, 2016

is there a way we can not have the fixture .gems like manticore commited? we could download them during bootstrap or install-development-dependencies?

@ph
Copy link
Contributor Author

ph commented Dec 29, 2016

@jsvd That path should be in the git ignore which will solve the problem, will push a fix for it.

@ph
Copy link
Contributor Author

ph commented Dec 29, 2016

@jsvd I've made sure we don't have any .gem.

@suyograo
Copy link
Contributor

LGTM.

@jsvd
Copy link
Member

jsvd commented Jan 3, 2017

LGTM

This new command replace the old workflow of `pack`, `unpack` and the `install --local`, and wrap all the logic into one uniform way of installing plugins.
The work is based on the flow developed for installing an x-pack inside Logstash, when you call prepare-offline-pack, the specified plugins and their dependencies will be packaged in a zip.
And this zip can be installed with the same flow as the pack.

Definition:

Source Logstash: Where you run the prepare-offline-pack.
Target Logstash: Where you install the offline package.

PROS:
- If you install a .gem in the source logstash, the .gem and his dependencies will be bundled.
- The install flow doesn't need to have access to the internet.
- Nothing special need to be setup in the target logstash environment.

CONS:
- The is one minor drawback, the plugins need to have their JARS bundled with them for this flow to work, this is currently the case for all the official plugins.
- The source Logstash need to have access to the internet when you install plugins before packaging them.

Usage examples:
bin/logstash-plugin prepare-offline-pack logstash-input-beats
bin/logstash-plugin prepare-offline-pack logstash-filter-jdbc logstash-input-beats
bin/logstash-plugin prepare-offline-pack logstash-filter-*
bin/logstash-plugin prepare-offline-pack logstash-filter-* logstash-input-beats

How to install:
bin/logstash-plugin install file:///tmp/logstash-offline-plugins-XXXX.zip
@elasticsearch-bot
Copy link

Pier-Hugues Pellerin merged this into the following branches!

Branch Commits
master fdda399
5.x 1b812af

elasticsearch-bot pushed a commit that referenced this pull request Jan 3, 2017
This new command replace the old workflow of `pack`, `unpack` and the `install --local`, and wrap all the logic into one uniform way of installing plugins.
The work is based on the flow developed for installing an x-pack inside Logstash, when you call prepare-offline-pack, the specified plugins and their dependencies will be packaged in a zip.
And this zip can be installed with the same flow as the pack.

Definition:

Source Logstash: Where you run the prepare-offline-pack.
Target Logstash: Where you install the offline package.

PROS:
- If you install a .gem in the source logstash, the .gem and his dependencies will be bundled.
- The install flow doesn't need to have access to the internet.
- Nothing special need to be setup in the target logstash environment.

CONS:
- The is one minor drawback, the plugins need to have their JARS bundled with them for this flow to work, this is currently the case for all the official plugins.
- The source Logstash need to have access to the internet when you install plugins before packaging them.

Usage examples:
bin/logstash-plugin prepare-offline-pack logstash-input-beats
bin/logstash-plugin prepare-offline-pack logstash-filter-jdbc logstash-input-beats
bin/logstash-plugin prepare-offline-pack logstash-filter-*
bin/logstash-plugin prepare-offline-pack logstash-filter-* logstash-input-beats

How to install:
bin/logstash-plugin install file:///tmp/logstash-offline-plugins-XXXX.zip

Fixes #6404
@acchen97
Copy link
Contributor

acchen97 commented Jan 5, 2017

Great work @ph. Users will rejoice. :)

@greenie69
Copy link

Not sure that this is the right spot to bring this up as I am new to ELK stack...
Running Windows Server 2012 R2 in offline lab:

  • Ran logstash filter with wildcard on Ubuntu system and then again on Windows 10...both came up with different size logstash-offline-plugins-5.3.0.zip (42MB & 32MB respectively)
  • using powershell ran command: .\bin\logstash-plugin install file: "C:\ELK\logstash-offline-plugins-5.3.0.zip" and both files ended up giving me the same error

Validating file:
Unable to download data from https://rubygems.org - SocketError: initialize: name or service not known (https://rubygems.org/latest_specs.4.8.gz)
Error: Installation aborted, verification failed for file:

Any help would be appreciated.

@acchen97
Copy link
Contributor

@greenie69 can you instead try the file:// syntax as specified in the docs?

@greenie69
Copy link

I have ran it with file:// and file:/// before, but ran them both again and the both give the same error

.\logstash-plugin install file:///C:\ELK\logstash-offline-plugins-5.3.0.zip

ERROR: Something went wrong when installing file:///C:\ELK\logstash-offline-plugins-5.3.0.zip, message: bad URI(is not URI?): https://artifacts.elastic.co/downloads/logstash-plugins/file:///c:\ELK\logstash-offline-plugins-5.3.0.zip/file:///C:\ELK\logstash-offline-plugins-5.3.0.zip-5.3.0.zip

@greenie69
Copy link

The only syntax that seems to work, but gives a different error is using the quotes:

PS C:\ELK\logstash-5.3.0\bin> .\logstash-plugin install file: "C:\ELK\logstash-offline-plugins-5.3.0.zip"
Using JAVA_HOME=C:\Program Files (x86)\Java\jre1.8.0_121 retrieved from C:\ProgramData\Oracle\java\javapath\java.exe
Validating file:
Plugin file: does not exist
ERROR: Installation aborted, verification failed for file:

@ph
Copy link
Contributor Author

ph commented Apr 11, 2017

@greenie69 did you try this format?

bin/logstash-plugin install file:///c:/elastic/install/plugins/x-pack-5.3.0.zip

@greenie69
Copy link

Yes...Finally...the confusing part is are the slashes..once I changed the slashes after the system drive letter that seemed to do the trick and it installed. Thanks ph

@tbaumann
Copy link

It needs to be much clearer that the path needs to be a file:// URI.
I just spent a long time trying to figure out why this didn't work. I would never use such URI unless specifically told.

But yea, thanks. It works once I figured it out. :)

@acchen97
Copy link
Contributor

The install from file use case is pretty clear in the docs. I can see some confusion when working on a Windows system though since backslashes may be the expected syntax.

@dedemorton is this something you could help clarify in the docs?

@dedemorton
Copy link
Contributor

@acchen97 Sure, I've submitted PR #7180 to indicate that the command accepts a file URI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants