mirror of
https://github.com/elastic/logstash.git
synced 2025-04-25 07:07:54 -04:00
Introduction of an update scenario for artifacts, including snapshot/restore for VM's and initial schema for this scenario.
Some other minor changes include: * add back the user level boostrap scripts, useful in that case to pull latest released LS * cleanup formatting for specs and fixed bootstrap scripts for redhats * make the latest logstash version available from the current platform config file * make sure debian based machines use java8 * make sure to use hostname and not just ip:port address when reporting the names Fixes #5350
This commit is contained in:
parent
ced5e5e020
commit
e52bda64c6
21 changed files with 194 additions and 115 deletions
|
@ -1,7 +1,7 @@
|
||||||
require "rspec"
|
require "rspec"
|
||||||
require "rspec/core/runner"
|
require "rspec/core/runner"
|
||||||
require "rspec/core/rake_task"
|
require "rspec/core/rake_task"
|
||||||
require_relative "vagrant-helpers"
|
require_relative "vagrant/helpers"
|
||||||
require_relative "platform_config"
|
require_relative "platform_config"
|
||||||
|
|
||||||
platforms = PlatformConfig.new
|
platforms = PlatformConfig.new
|
||||||
|
|
4
qa/Vagrantfile
vendored
4
qa/Vagrantfile
vendored
|
@ -17,6 +17,10 @@ Vagrant.configure(2) do |config|
|
||||||
sh.path = "sys/#{platform.type}/bootstrap.sh"
|
sh.path = "sys/#{platform.type}/bootstrap.sh"
|
||||||
sh.privileged = true
|
sh.privileged = true
|
||||||
end
|
end
|
||||||
|
machine.vm.provision :shell do |sh|
|
||||||
|
sh.path = "sys/#{platform.type}/user_bootstrap.sh"
|
||||||
|
sh.privileged = false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
require_relative '../spec_helper'
|
require_relative '../spec_helper'
|
||||||
require_relative '../shared_examples/installed'
|
require_relative '../shared_examples/installed'
|
||||||
require_relative '../shared_examples/running'
|
require_relative '../shared_examples/running'
|
||||||
|
require_relative '../shared_examples/updated'
|
||||||
|
|
||||||
describe "artifacts operation" do
|
describe "artifacts operation" do
|
||||||
config = ServiceTester.configuration
|
config = ServiceTester.configuration
|
||||||
config.servers.each do |address|
|
config.servers.each do |address|
|
||||||
logstash = ServiceTester::Artifact.new(address, config.lookup[address])
|
logstash = ServiceTester::Artifact.new(address, config.lookup[address])
|
||||||
it_behaves_like "installable", logstash
|
it_behaves_like "installable", logstash
|
||||||
it_behaves_like "runnable", logstash
|
it_behaves_like "updated", logstash
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,17 +7,17 @@ RSpec.shared_examples "installable" do |logstash|
|
||||||
logstash.install(LOGSTASH_VERSION)
|
logstash.install(LOGSTASH_VERSION)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is installed on #{logstash.host}" do
|
it "is installed on #{logstash.hostname}" do
|
||||||
expect(logstash).to be_installed
|
expect(logstash).to be_installed
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is running on #{logstash.host}" do
|
it "is running on #{logstash.hostname}" do
|
||||||
logstash.start_service
|
logstash.start_service
|
||||||
expect(logstash).to be_running
|
expect(logstash).to be_running
|
||||||
logstash.stop_service
|
logstash.stop_service
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is removable on #{logstash.host}" do
|
it "is removable on #{logstash.hostname}" do
|
||||||
logstash.uninstall
|
logstash.uninstall
|
||||||
expect(logstash).to be_removed
|
expect(logstash).to be_removed
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ RSpec.shared_examples "runnable" do |logstash|
|
||||||
logstash.install(LOGSTASH_VERSION)
|
logstash.install(LOGSTASH_VERSION)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is running on #{logstash.host}" do
|
it "is running on #{logstash.hostname}" do
|
||||||
logstash.start_service
|
logstash.start_service
|
||||||
expect(logstash).to be_running
|
expect(logstash).to be_running
|
||||||
logstash.stop_service
|
logstash.stop_service
|
||||||
|
|
21
qa/acceptance/spec/shared_examples/updated.rb
Normal file
21
qa/acceptance/spec/shared_examples/updated.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
require_relative '../spec_helper'
|
||||||
|
require 'logstash/version'
|
||||||
|
|
||||||
|
RSpec.shared_examples "updated" do |logstash|
|
||||||
|
|
||||||
|
before (:all) { logstash.snapshot }
|
||||||
|
after (:all) { logstash.restore }
|
||||||
|
|
||||||
|
it "can update on #{logstash.hostname}" do
|
||||||
|
logstash.install(LOGSTASH_LATEST_VERSION, "./")
|
||||||
|
expect(logstash).to be_installed
|
||||||
|
logstash.install(LOGSTASH_VERSION)
|
||||||
|
expect(logstash).to be_installed
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can run on #{logstash.hostname}" do
|
||||||
|
logstash.start_service
|
||||||
|
expect(logstash).to be_running
|
||||||
|
logstash.stop_service
|
||||||
|
end
|
||||||
|
end
|
|
@ -17,6 +17,8 @@ end
|
||||||
platform = ENV['LS_TEST_PLATFORM'] || 'all'
|
platform = ENV['LS_TEST_PLATFORM'] || 'all'
|
||||||
|
|
||||||
config = PlatformConfig.new
|
config = PlatformConfig.new
|
||||||
|
LOGSTASH_LATEST_VERSION = config.latest
|
||||||
|
|
||||||
default_vagrant_boxes = ( platform == 'all' ? config.platforms : config.filter_type(platform) )
|
default_vagrant_boxes = ( platform == 'all' ? config.platforms : config.filter_type(platform) )
|
||||||
|
|
||||||
selected_boxes = if ENV.include?('LS_VAGRANT_HOST') then
|
selected_boxes = if ENV.include?('LS_VAGRANT_HOST') then
|
||||||
|
|
16
qa/config/platforms.json
Normal file
16
qa/config/platforms.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"latest": "5.0.0-alpha2",
|
||||||
|
"platforms" : {
|
||||||
|
"ubuntu-1204": { "box": "elastic/ubuntu-12.04-x86_64", "type": "debian" },
|
||||||
|
"ubuntu-1404": { "box": "elastic/ubuntu-14.04-x86_64", "type": "debian" },
|
||||||
|
"ubuntu-1504": { "box": "elastic/ubuntu-15.04-x86_64", "type": "debian" },
|
||||||
|
"centos-6": { "box": "elastic/centos-6-x86_64", "type": "redhat" },
|
||||||
|
"centos-7": { "box": "elastic/centos-7-x86_64", "type": "redhat" },
|
||||||
|
"oel-6": { "box": "elastic/oraclelinux-6-x86_64", "type": "redhat" },
|
||||||
|
"oel-7": { "box": "elastic/oraclelinux-7-x86_64", "type": "redhat" },
|
||||||
|
"fedora-22": { "box": "elastic/fedora-22-x86_64", "type": "redhat" },
|
||||||
|
"debian-8": { "box": "elastic/debian-8-x86_64", "type": "debian" },
|
||||||
|
"opensuse-13": { "box": "elastic/opensuse-13-x86_64", "type": "suse" },
|
||||||
|
"sles-12": { "box": "elastic/sles-12-x86_64", "type": "suse" }
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,20 +5,20 @@ class PlatformConfig
|
||||||
|
|
||||||
Platform = Struct.new(:name, :box, :type)
|
Platform = Struct.new(:name, :box, :type)
|
||||||
|
|
||||||
DEFAULT_CONFIG_LOCATION = File.join(File.dirname(__FILE__), "platforms.json").freeze
|
DEFAULT_CONFIG_LOCATION = File.join(File.dirname(__FILE__), "config", "platforms.json").freeze
|
||||||
|
|
||||||
attr_reader :platforms
|
attr_reader :platforms, :latest
|
||||||
|
|
||||||
def initialize(config_path = DEFAULT_CONFIG_LOCATION)
|
def initialize(config_path = DEFAULT_CONFIG_LOCATION)
|
||||||
@config_path = config_path
|
@config_path = config_path
|
||||||
@platforms = []
|
@platforms = []
|
||||||
|
|
||||||
data = JSON.parse(File.read(@config_path))
|
data = JSON.parse(File.read(@config_path))
|
||||||
data.each do |k, v|
|
data["platforms"].each do |k, v|
|
||||||
@platforms << Platform.new(k, v["box"], v["type"])
|
@platforms << Platform.new(k, v["box"], v["type"])
|
||||||
end
|
end
|
||||||
|
|
||||||
@platforms.sort! { |a, b| a.name <=> b.name }
|
@platforms.sort! { |a, b| a.name <=> b.name }
|
||||||
|
@latest = data["latest"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def find!(platform_name)
|
def find!(platform_name)
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"ubuntu-1204": { "box": "elastic/ubuntu-12.04-x86_64", "type": "debian" },
|
|
||||||
"ubuntu-1404": { "box": "elastic/ubuntu-14.04-x86_64", "type": "debian" },
|
|
||||||
"ubuntu-1504": { "box": "elastic/ubuntu-15.04-x86_64", "type": "debian" },
|
|
||||||
"centos-6": { "box": "elastic/centos-6-x86_64", "type": "redhat" },
|
|
||||||
"centos-7": { "box": "elastic/centos-7-x86_64", "type": "redhat" },
|
|
||||||
"oel-6": { "box": "elastic/oraclelinux-6-x86_64", "type": "redhat" },
|
|
||||||
"oel-7": { "box": "elastic/oraclelinux-7-x86_64", "type": "redhat" },
|
|
||||||
"fedora-22": { "box": "elastic/fedora-22-x86_64", "type": "redhat" },
|
|
||||||
"debian-8": { "box": "elastic/debian-8-x86_64", "type": "debian" },
|
|
||||||
"opensuse-13": { "box": "elastic/opensuse-13-x86_64", "type": "suse" },
|
|
||||||
"sles-12": { "box": "elastic/sles-12-x86_64", "type": "suse" }
|
|
||||||
}
|
|
|
@ -20,6 +20,10 @@ module ServiceTester
|
||||||
@client = CommandsFactory.fetch(options["type"], options["host"])
|
@client = CommandsFactory.fetch(options["type"], options["host"])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def hostname
|
||||||
|
@options["host"]
|
||||||
|
end
|
||||||
|
|
||||||
def name
|
def name
|
||||||
"logstash"
|
"logstash"
|
||||||
end
|
end
|
||||||
|
@ -28,6 +32,14 @@ module ServiceTester
|
||||||
[@host]
|
[@host]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def snapshot
|
||||||
|
client.snapshot(@options["host"])
|
||||||
|
end
|
||||||
|
|
||||||
|
def restore
|
||||||
|
client.restore(@options["host"])
|
||||||
|
end
|
||||||
|
|
||||||
def start_service
|
def start_service
|
||||||
client.start_service(name, host)
|
client.start_service(name, host)
|
||||||
end
|
end
|
||||||
|
@ -36,8 +48,8 @@ module ServiceTester
|
||||||
client.stop_service(name, host)
|
client.stop_service(name, host)
|
||||||
end
|
end
|
||||||
|
|
||||||
def install(version)
|
def install(version, base=ServiceTester::Base::LOCATION)
|
||||||
package = client.package_for(version)
|
package = client.package_for(version, base)
|
||||||
client.install(package, host)
|
client.install(package, host)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
require_relative "../../vagrant/helpers"
|
||||||
|
|
||||||
module ServiceTester
|
module ServiceTester
|
||||||
|
|
||||||
|
@ -6,6 +7,14 @@ module ServiceTester
|
||||||
|
|
||||||
LOCATION="/logstash-build".freeze
|
LOCATION="/logstash-build".freeze
|
||||||
|
|
||||||
|
def snapshot(host)
|
||||||
|
LogStash::VagrantHelpers.save_snapshot(host)
|
||||||
|
end
|
||||||
|
|
||||||
|
def restore(host)
|
||||||
|
LogStash::VagrantHelpers.restore_snapshot(host)
|
||||||
|
end
|
||||||
|
|
||||||
def start_service(service, host=nil)
|
def start_service(service, host=nil)
|
||||||
service_manager(service, "start", host)
|
service_manager(service, "start", host)
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,8 +14,8 @@ module ServiceTester
|
||||||
stdout.match(/^Status: install ok installed$/)
|
stdout.match(/^Status: install ok installed$/)
|
||||||
end
|
end
|
||||||
|
|
||||||
def package_for(version)
|
def package_for(version, base=ServiceTester::Base::LOCATION)
|
||||||
File.join(ServiceTester::Base::LOCATION, "logstash-#{version}_all.deb")
|
File.join(base, "logstash-#{version}_all.deb")
|
||||||
end
|
end
|
||||||
|
|
||||||
def install(package, host=nil)
|
def install(package, host=nil)
|
||||||
|
|
|
@ -14,8 +14,8 @@ module ServiceTester
|
||||||
stdout.match(/^logstash.noarch/)
|
stdout.match(/^logstash.noarch/)
|
||||||
end
|
end
|
||||||
|
|
||||||
def package_for(version)
|
def package_for(version, base=ServiceTester::Base::LOCATION)
|
||||||
File.join(ServiceTester::Base::LOCATION, "logstash-#{version}.noarch.rpm")
|
File.join(base, "logstash-#{version}.noarch.rpm")
|
||||||
end
|
end
|
||||||
|
|
||||||
def install(package, host=nil)
|
def install(package, host=nil)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
add-apt-repository ppa:openjdk-r/ppa
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y openjdk-7-jdk
|
apt-get install -y openjdk-8-jdk
|
||||||
|
update-alternatives --config java
|
||||||
|
update-alternatives --config javac
|
||||||
|
|
5
qa/sys/debian/user_bootstrap.sh
Normal file
5
qa/sys/debian/user_bootstrap.sh
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
VERSION=`cat /vagrant/config/platforms.json | grep latest | cut -d":" -f2 | sed 's/["\|,| ]//g'`
|
||||||
|
LOGSTASH_FILENAME="logstash-${VERSION}_all.deb"
|
||||||
|
wget -q https://download.elastic.co/logstash/logstash/packages/debian/$LOGSTASH_FILENAME
|
5
qa/sys/redhat/user_bootstrap.sh
Normal file
5
qa/sys/redhat/user_bootstrap.sh
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
VERSION=`cat /vagrant/config/platforms.json | grep latest | cut -d":" -f2 | sed 's/["\|,| ]//g'`
|
||||||
|
LOGSTASH_FILENAME="logstash-${VERSION}.noarch.rpm"
|
||||||
|
wget -q https://download.elastic.co/logstash/logstash/packages/centos/$LOGSTASH_FILENAME
|
1
qa/sys/suse/user_bootstrap.sh
Normal file
1
qa/sys/suse/user_bootstrap.sh
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#!/usr/bin/env bash
|
|
@ -1,84 +0,0 @@
|
||||||
# encoding: utf-8
|
|
||||||
require "open3"
|
|
||||||
require "bundler"
|
|
||||||
|
|
||||||
module LogStash
|
|
||||||
class CommandExecutor
|
|
||||||
class CommandError < StandardError; end
|
|
||||||
|
|
||||||
class CommandResponse
|
|
||||||
attr_reader :stdin, :stdout, :stderr, :exitstatus
|
|
||||||
|
|
||||||
def initialize(stdin, stdout, stderr, exitstatus)
|
|
||||||
@stdin = stdin,
|
|
||||||
@stdout = stdout
|
|
||||||
@stderr = stderr
|
|
||||||
@exitstatus = exitstatus
|
|
||||||
end
|
|
||||||
|
|
||||||
def success?
|
|
||||||
exitstatus == 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.run(cmd)
|
|
||||||
# This block is require to be able to launch a ruby subprocess
|
|
||||||
# that use bundler.
|
|
||||||
Bundler.with_clean_env do
|
|
||||||
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
|
||||||
CommandResponse.new(stdin, stdout.read.chomp, stderr.read.chomp, wait_thr.value.exitstatus)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method will raise an exception if the `CMD`
|
|
||||||
# was not run successfully and will display the content of STDERR
|
|
||||||
def self.run!(cmd)
|
|
||||||
response = run(cmd)
|
|
||||||
|
|
||||||
unless response.success?
|
|
||||||
raise CommandError, "CMD: #{cmd} STDERR: #{response.stderr}"
|
|
||||||
end
|
|
||||||
response
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class VagrantHelpers
|
|
||||||
|
|
||||||
def self.halt(machines="")
|
|
||||||
CommandExecutor.run!("vagrant halt #{machines.join(' ')}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.destroy(machines="")
|
|
||||||
CommandExecutor.run!("vagrant destroy --force #{machines.join(' ')}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.bootstrap(machines="")
|
|
||||||
CommandExecutor.run!("vagrant up #{machines.join(' ')}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.fetch_config
|
|
||||||
cmd = CommandExecutor.run!("vagrant status")
|
|
||||||
machines = cmd.stdout.split("\n").select { |m| m.include?("running") }.map { |s| s.split(" ")[0] }
|
|
||||||
CommandExecutor.run!("vagrant ssh-config #{machines.join(' ')}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.parse(lines)
|
|
||||||
hosts, host = [], {}
|
|
||||||
lines.each do |line|
|
|
||||||
if line.match(/Host\s(.*)$/)
|
|
||||||
host = { :host => line.gsub("Host","").strip }
|
|
||||||
elsif line.match(/HostName\s(.*)$/)
|
|
||||||
host[:hostname] = line.gsub("HostName","").strip
|
|
||||||
elsif line.match(/Port\s(.*)$/)
|
|
||||||
host[:port] = line.gsub("Port","").strip
|
|
||||||
elsif line.empty?
|
|
||||||
hosts << host
|
|
||||||
host = {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
hosts << host
|
|
||||||
hosts
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
45
qa/vagrant/command.rb
Normal file
45
qa/vagrant/command.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require "open3"
|
||||||
|
require "bundler"
|
||||||
|
|
||||||
|
module LogStash
|
||||||
|
class CommandExecutor
|
||||||
|
class CommandError < StandardError; end
|
||||||
|
|
||||||
|
class CommandResponse
|
||||||
|
attr_reader :stdin, :stdout, :stderr, :exitstatus
|
||||||
|
|
||||||
|
def initialize(stdin, stdout, stderr, exitstatus)
|
||||||
|
@stdin = stdin
|
||||||
|
@stdout = stdout
|
||||||
|
@stderr = stderr
|
||||||
|
@exitstatus = exitstatus
|
||||||
|
end
|
||||||
|
|
||||||
|
def success?
|
||||||
|
exitstatus == 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.run(cmd)
|
||||||
|
# This block is require to be able to launch a ruby subprocess
|
||||||
|
# that use bundler.
|
||||||
|
Bundler.with_clean_env do
|
||||||
|
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
||||||
|
CommandResponse.new(stdin, stdout.read.chomp, stderr.read.chomp, wait_thr.value.exitstatus)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# This method will raise an exception if the `CMD`
|
||||||
|
# was not run successfully and will display the content of STDERR
|
||||||
|
def self.run!(cmd)
|
||||||
|
response = run(cmd)
|
||||||
|
|
||||||
|
unless response.success?
|
||||||
|
raise CommandError, "CMD: #{cmd} STDERR: #{response.stderr}"
|
||||||
|
end
|
||||||
|
response
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
52
qa/vagrant/helpers.rb
Normal file
52
qa/vagrant/helpers.rb
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require "open3"
|
||||||
|
require "bundler"
|
||||||
|
require_relative "command"
|
||||||
|
|
||||||
|
module LogStash
|
||||||
|
class VagrantHelpers
|
||||||
|
|
||||||
|
def self.halt(machines="")
|
||||||
|
CommandExecutor.run!("vagrant halt #{machines.join(' ')}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.destroy(machines="")
|
||||||
|
CommandExecutor.run!("vagrant destroy --force #{machines.join(' ')}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.bootstrap(machines="")
|
||||||
|
CommandExecutor.run!("vagrant up #{machines.join(' ')}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.save_snapshot(machine="")
|
||||||
|
CommandExecutor.run!("vagrant snapshot save #{machine} #{machine}-snapshot")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.restore_snapshot(machine="")
|
||||||
|
CommandExecutor.run!("vagrant snapshot restore #{machine} #{machine}-snapshot")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.fetch_config
|
||||||
|
machines = CommandExecutor.run!("vagrant status").stdout.split("\n").select { |l| l.include?("running") }.map { |r| r.split(' ')[0]}
|
||||||
|
CommandExecutor.run!("vagrant ssh-config #{machines.join(' ')}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.parse(lines)
|
||||||
|
hosts, host = [], {}
|
||||||
|
lines.each do |line|
|
||||||
|
if line.match(/Host\s(.*)$/)
|
||||||
|
host = { :host => line.gsub("Host","").strip }
|
||||||
|
elsif line.match(/HostName\s(.*)$/)
|
||||||
|
host[:hostname] = line.gsub("HostName","").strip
|
||||||
|
elsif line.match(/Port\s(.*)$/)
|
||||||
|
host[:port] = line.gsub("Port","").strip
|
||||||
|
elsif line.empty?
|
||||||
|
hosts << host
|
||||||
|
host = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hosts << host
|
||||||
|
hosts
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Add a link
Reference in a new issue