logstash/lib/bootstrap/util/compress.rb
Pier-Hugues Pellerin 00e225a849 Feature: A way to install/remove a plugin pack
A pack in this context is a *bundle* of plugins that can be distributed outside of rubygems; it is similar to what ES and kibana are doing, and
the user interface is modeled after them. See https://www.elastic.co/downloads/x-pack

**Do not mix it with the `bin/logstash-plugin pack/unpack` command.**

- it contains one or more plugins that need to be installed
- it is self-contains with the gems and the needed jars
- it is distributed as a zip file
- the file structure needs to follow some rules.

- As a reserved name name on elastic.co download http server
    - `bin/plugin install logstash-mypack` will check on the download server if a pack for the current specific logstash version exist and it will be downloaded, if it doesn't exist we fallback on rubygems.
    - The file on the server will follow this convention `logstash-mypack-{LOGSTASH_VERSION}.zip`

- As a fully qualified url
    - `bin/plugin install http://test.abc/logstash-mypack.zip`, if it exists it will be downloaded and installed if it does not we raise an error.

- As a local file
    - `bin/plugin install file:///tmp/logstash-mypack.zip`, if it exists it will be installed

Fixes #6168
2016-11-17 14:00:02 -05:00

122 lines
4.1 KiB
Ruby

# encoding: utf-8
require "zip"
require "rubygems/package"
require "fileutils"
require "zlib"
require "stud/temporary"
module LogStash
class CompressError < StandardError; end
module Util
module Zip
extend self
# Extract a zip file into a destination directory.
# @param source [String] The location of the file to extract
# @param target [String] Where you do want the file to be extracted
# @raise [IOError] If the target directory already exist
def extract(source, target, pattern = nil)
raise CompressError.new("Directory #{target} exist") if ::File.exist?(target)
::Zip::File.open(source) do |zip_file|
zip_file.each do |file|
path = ::File.join(target, file.name)
FileUtils.mkdir_p(::File.dirname(path))
zip_file.extract(file, path) if pattern.nil? || pattern =~ file.name
end
end
end
# Compress a directory into a zip file
# @param dir [String] The directory to be compressed
# @param target [String] Destination to save the generated file
# @raise [IOError] If the target file already exist
def compress(dir, target)
raise CompressError.new("File #{target} exist") if ::File.exist?(target)
::Zip::File.open(target, ::Zip::File::CREATE) do |zipfile|
Dir.glob("#{dir}/**/*").each do |file|
path_in_zip = file.gsub("#{dir}/","")
zipfile.add(path_in_zip, file)
end
end
end
end
module Tar
extend self
# Extract a tar.gz file into a destination directory.
# @param source [String] The location of the file to extract
# @param target [String] Where you do want the file to be extracted
# @raise [IOError] If the target directory already exist
def extract(file, target)
raise CompressError.new("Directory #{target} exist") if ::File.exist?(target)
FileUtils.mkdir(target)
Zlib::GzipReader.open(file) do |gzip_file|
::Gem::Package::TarReader.new(gzip_file) do |tar_file|
tar_file.each do |entry|
target_path = ::File.join(target, entry.full_name)
if entry.directory?
FileUtils.mkdir_p(target_path)
else # is a file to be extracted
::File.open(target_path, "wb") { |f| f.write(entry.read) }
end
end
end
end
end
# Compress a directory into a tar.gz file
# @param dir [String] The directory to be compressed
# @param target [String] Destination to save the generated file
# @raise [IOError] If the target file already exist
def compress(dir, target)
raise CompressError.new("File #{target} exist") if ::File.exist?(target)
Stud::Temporary.file do |tar_file|
::Gem::Package::TarWriter.new(tar_file) do |tar|
Dir.glob("#{dir}/**/*").each do |file|
name = file.gsub("#{dir}/","")
stats = ::File.stat(file)
mode = stats.mode
if ::File.directory?(file)
tar.mkdir(name, mode)
else # is a file to be added
tar.add_file(name,mode) do |out|
File.open(file, "rb") do |fd|
chunk = nil
size = 0
size += out.write(chunk) while chunk = fd.read(16384)
if stats.size != size
raise "Failure to write the entire file (#{path}) to the tarball. Expected to write #{stats.size} bytes; actually write #{size}"
end
end
end
end
end
end
tar_file.rewind
gzip(target, tar_file)
end
end
# Compress a file using gzip
# @param path [String] The location to be compressed
# @param target_file [String] Destination of the generated file
def gzip(path, target_file)
::File.open(path, "wb") do |file|
gzip_file = ::Zlib::GzipWriter.new(file)
gzip_file.write(target_file.read)
gzip_file.close
end
end
end
end
end