logstash-input-snmp 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/docs/index.asciidoc +1 -0
- data/lib/logstash/inputs/snmp.rb +50 -4
- data/logstash-input-snmp.gemspec +1 -1
- data/spec/inputs/integration/it_spec.rb +203 -0
- data/spec/inputs/snmp/interval_runner_spec.rb +0 -0
- data/spec/inputs/snmp_spec.rb +90 -0
- data/vendor/jar-dependencies/org/snmp4j/snmp4j/2.5.11/snmp4j-2.5.11.jar +0 -0
- metadata +8 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 4bcb5f73151249317b6f7b36c028a3f863e7d4a88ba6da977fbc88d255355364
         | 
| 4 | 
            +
              data.tar.gz: 85ef765af5f93aefb92a8f40d9738101ada3b5173bb9b4b8de3d4ec21a406578
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 423f10e23a58b04a72c47d70beb06053dedc8d07e1ec1e36c835ca783c6791bb6ccd12d701d3e50bd4ebe173185a4240ae21a93c36d7ecdf38bf4e2ae6d58f25
         | 
| 7 | 
            +
              data.tar.gz: f452759e6c453d088b002721ae1520b1c22291e16ff609d8f308e57c3e9aa9dc29b008c809a9a6a76e76b00e68c0399fc96b63f23dc066aa403a682f19712f2e
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,9 @@ | |
| 1 | 
            +
            ## 1.2.8
         | 
| 2 | 
            +
              - Fixed interval handling to only sleep off the _remainder_ of the interval (if any), and to log a helpful warning when crawling the hosts takes longer than the configured interval [#61](https://github.com/logstash-plugins/logstash-input-snmp/issues/61)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            ## 1.2.7
         | 
| 5 | 
            +
              - Added integration tests to ensure SNMP server and IPv6 connections [#87](https://github.com/logstash-plugins/logstash-input-snmp/pull/87)
         | 
| 6 | 
            +
             | 
| 1 7 | 
             
            ## 1.2.6
         | 
| 2 8 | 
             
              - Docs: example on setting IPv6 hosts [#89](https://github.com/logstash-plugins/logstash-input-snmp/pull/89)
         | 
| 3 9 |  | 
    
        data/docs/index.asciidoc
    CHANGED
    
    | @@ -163,6 +163,7 @@ input { | |
| 163 163 | 
             
            ===== `interval` 
         | 
| 164 164 |  | 
| 165 165 | 
             
            The `interval` option specifies the polling interval in seconds.
         | 
| 166 | 
            +
            If polling all configured hosts takes longer than this interval, a warning will be emitted to the logs.
         | 
| 166 167 |  | 
| 167 168 | 
             
            * Value type is <<number,number>>
         | 
| 168 169 | 
             
            * Default value is `30`
         | 
    
        data/lib/logstash/inputs/snmp.rb
    CHANGED
    
    | @@ -161,9 +161,9 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base | |
| 161 161 | 
             
              end
         | 
| 162 162 |  | 
| 163 163 | 
             
              def run(queue)
         | 
| 164 | 
            -
                # for now a naive single threaded poller which sleeps  | 
| 164 | 
            +
                # for now a naive single threaded poller which sleeps off the remaining interval between
         | 
| 165 165 | 
             
                # each run. each run polls all the defined hosts for the get and walk options.
         | 
| 166 | 
            -
                 | 
| 166 | 
            +
                stoppable_interval_runner.every(@interval, "polling hosts") do
         | 
| 167 167 | 
             
                  @client_definitions.each do |definition|
         | 
| 168 168 | 
             
                    result = {}
         | 
| 169 169 | 
             
                    if !definition[:get].empty?
         | 
| @@ -207,11 +207,13 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base | |
| 207 207 | 
             
                      queue << event
         | 
| 208 208 | 
             
                    end
         | 
| 209 209 | 
             
                  end
         | 
| 210 | 
            -
             | 
| 211 | 
            -
                  Stud.stoppable_sleep(@interval) { stop? }
         | 
| 212 210 | 
             
                end
         | 
| 213 211 | 
             
              end
         | 
| 214 212 |  | 
| 213 | 
            +
              def stoppable_interval_runner
         | 
| 214 | 
            +
                StoppableIntervalRunner.new(self)
         | 
| 215 | 
            +
              end
         | 
| 216 | 
            +
             | 
| 215 217 | 
             
              def close
         | 
| 216 218 | 
             
                @client_definitions.each do |definition|
         | 
| 217 219 | 
             
                  begin
         | 
| @@ -222,6 +224,9 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base | |
| 222 224 | 
             
                end
         | 
| 223 225 | 
             
              end
         | 
| 224 226 |  | 
| 227 | 
            +
              def stop
         | 
| 228 | 
            +
              end
         | 
| 229 | 
            +
             | 
| 225 230 | 
             
              private
         | 
| 226 231 |  | 
| 227 232 | 
             
              OID_REGEX = /^\.?([0-9\.]+)$/
         | 
| @@ -295,4 +300,45 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base | |
| 295 300 | 
             
              def validate_strip!
         | 
| 296 301 | 
             
                raise(LogStash::ConfigurationError, "you can not specify both oid_root_skip and oid_path_length") if @oid_root_skip > 0 and @oid_path_length > 0
         | 
| 297 302 | 
             
              end
         | 
| 303 | 
            +
             | 
| 304 | 
            +
              ##
         | 
| 305 | 
            +
              # The StoppableIntervalRunner is capable of running a block of code at a
         | 
| 306 | 
            +
              # repeating interval, while respecting the stop condition of the plugin.
         | 
| 307 | 
            +
              class StoppableIntervalRunner
         | 
| 308 | 
            +
                ##
         | 
| 309 | 
            +
                # @param plugin [#logger,#stop?]
         | 
| 310 | 
            +
                def initialize(plugin)
         | 
| 311 | 
            +
                  @plugin = plugin
         | 
| 312 | 
            +
                end
         | 
| 313 | 
            +
             | 
| 314 | 
            +
                ##
         | 
| 315 | 
            +
                # Runs the provided block repeatedly using the provided interval.
         | 
| 316 | 
            +
                # After executing the block, the remainder of the interval if any is slept off
         | 
| 317 | 
            +
                # using an interruptible sleep.
         | 
| 318 | 
            +
                # If no time remains, a warning is emitted to the logs.
         | 
| 319 | 
            +
                #
         | 
| 320 | 
            +
                # @param interval_seconds [Integer,Float]
         | 
| 321 | 
            +
                # @param desc [String] (default: "operation"): a description to use when logging
         | 
| 322 | 
            +
                # @yield
         | 
| 323 | 
            +
                def every(interval_seconds, desc="operation", &block)
         | 
| 324 | 
            +
                  until @plugin.stop?
         | 
| 325 | 
            +
                    start_time = Time.now
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                    yield
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                    duration_seconds = Time.now - start_time
         | 
| 330 | 
            +
                    if duration_seconds >= interval_seconds
         | 
| 331 | 
            +
                      @plugin.logger.warn("#{desc} took longer than the configured interval", :interval_seconds => interval_seconds, :duration_seconds => duration_seconds.round(3))
         | 
| 332 | 
            +
                    else
         | 
| 333 | 
            +
                      remaining_interval = interval_seconds - duration_seconds
         | 
| 334 | 
            +
                      sleep(remaining_interval)
         | 
| 335 | 
            +
                    end
         | 
| 336 | 
            +
                  end
         | 
| 337 | 
            +
                end
         | 
| 338 | 
            +
             | 
| 339 | 
            +
                # @api private
         | 
| 340 | 
            +
                def sleep(duration)
         | 
| 341 | 
            +
                  Stud.stoppable_sleep(duration) { @plugin.stop? }
         | 
| 342 | 
            +
                end
         | 
| 343 | 
            +
              end
         | 
| 298 344 | 
             
            end
         | 
    
        data/logstash-input-snmp.gemspec
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 | 
             
              s.name          = 'logstash-input-snmp'
         | 
| 3 | 
            -
              s.version       = '1.2. | 
| 3 | 
            +
              s.version       = '1.2.8'
         | 
| 4 4 | 
             
              s.licenses      = ['Apache-2.0']
         | 
| 5 5 | 
             
              s.summary       = "SNMP input plugin"
         | 
| 6 6 | 
             
              s.description   = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
         | 
| @@ -0,0 +1,203 @@ | |
| 1 | 
            +
            require "logstash/devutils/rspec/spec_helper"
         | 
| 2 | 
            +
            require "logstash/inputs/snmp"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe LogStash::Inputs::Snmp do
         | 
| 5 | 
            +
              let(:config) { {"get" => ["1.3.6.1.2.1.1.1.0", "1.3.6.1.2.1.1.3.0", "1.3.6.1.2.1.1.5.0"]} }
         | 
| 6 | 
            +
              let(:plugin) { LogStash::Inputs::Snmp.new(config)}
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              shared_examples "snmp plugin return single event" do
         | 
| 9 | 
            +
                it "should have OID value" do
         | 
| 10 | 
            +
                  plugin.register
         | 
| 11 | 
            +
                  queue = []
         | 
| 12 | 
            +
                  stop_plugin_after_seconds(plugin)
         | 
| 13 | 
            +
                  plugin.run(queue)
         | 
| 14 | 
            +
                  plugin.close
         | 
| 15 | 
            +
                  event = queue.pop
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  expect(event).to be_a(LogStash::Event)
         | 
| 18 | 
            +
                  expect(event.get("iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance")).to be_a Integer
         | 
| 19 | 
            +
                  expect(event.get("iso.org.dod.internet.mgmt.mib-2.system.sysName.0")).to be_a String
         | 
| 20 | 
            +
                  expect(event.get("iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0")).to be_a String
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              shared_examples "snmp plugin return one udp event and one tcp event" do |config|
         | 
| 25 | 
            +
                it "should have one udp from snmp1 and one tcp from snmp2" do
         | 
| 26 | 
            +
                  events = input(config) { |_, queue| 2.times.collect { queue.pop } }
         | 
| 27 | 
            +
                  udp = 0; tcp = 0
         | 
| 28 | 
            +
                  events.each { |event|
         | 
| 29 | 
            +
                    if event.get("[@metadata][host_protocol]") == "udp"
         | 
| 30 | 
            +
                      udp += 1
         | 
| 31 | 
            +
                      expect(event.get("[@metadata][host_protocol]")).to eq("udp")
         | 
| 32 | 
            +
                      expect(event.get("[@metadata][host_address]")).to eq("snmp1")
         | 
| 33 | 
            +
                      expect(event.get("[@metadata][host_port]")).to eq("161")
         | 
| 34 | 
            +
                    else
         | 
| 35 | 
            +
                      tcp += 1
         | 
| 36 | 
            +
                      expect(event.get("[@metadata][host_protocol]")).to eq("tcp")
         | 
| 37 | 
            +
                      expect(event.get("[@metadata][host_address]")).to eq("snmp2")
         | 
| 38 | 
            +
                      expect(event.get("[@metadata][host_port]")).to eq("162")
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  }
         | 
| 41 | 
            +
                  expect(udp).to eq(1)
         | 
| 42 | 
            +
                  expect(tcp).to eq(1)
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              describe "against single snmp server with snmpv2 and udp", :integration => true do
         | 
| 47 | 
            +
                let(:config) { super().merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}]})}
         | 
| 48 | 
            +
                it_behaves_like "snmp plugin return single event"
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              describe "against single server with snmpv3 and tcp", :integration => true do
         | 
| 52 | 
            +
                let(:config) { super().merge({
         | 
| 53 | 
            +
                   "hosts" => [{"host" => "tcp:snmp1/161", "version" => "3"}],
         | 
| 54 | 
            +
                   "security_name" => "user_1",
         | 
| 55 | 
            +
                   "auth_protocol" => "sha",
         | 
| 56 | 
            +
                   "auth_pass" => "STrP@SSPhr@sE",
         | 
| 57 | 
            +
                   "priv_protocol" => "aes",
         | 
| 58 | 
            +
                   "priv_pass" => "STr0ngP@SSWRD161",
         | 
| 59 | 
            +
                   "security_level" => "authPriv"
         | 
| 60 | 
            +
                                           })}
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                it_behaves_like "snmp plugin return single event"
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              describe "invalid user against snmpv3 server", :integration => true do
         | 
| 66 | 
            +
                let(:config) { super().merge({
         | 
| 67 | 
            +
                                               "hosts" => [{"host" => "tcp:snmp1/161", "version" => "3"}],
         | 
| 68 | 
            +
                                               "security_name" => "user_2",
         | 
| 69 | 
            +
                                               "auth_protocol" => "sha",
         | 
| 70 | 
            +
                                               "auth_pass" => "STrP@SSPhr@sE",
         | 
| 71 | 
            +
                                               "priv_protocol" => "aes",
         | 
| 72 | 
            +
                                               "priv_pass" => "STr0ngP@SSWRD161",
         | 
| 73 | 
            +
                                               "security_level" => "authPriv"
         | 
| 74 | 
            +
                                           })}
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                it "should have error log" do
         | 
| 77 | 
            +
                  expect(plugin.logger).to receive(:error).once
         | 
| 78 | 
            +
                  plugin.register
         | 
| 79 | 
            +
                  queue = []
         | 
| 80 | 
            +
                  stop_plugin_after_seconds(plugin)
         | 
| 81 | 
            +
                  plugin.run(queue)
         | 
| 82 | 
            +
                  plugin.close
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              describe "single input plugin on single server with snmpv2 and mix of udp and tcp", :integration => true do
         | 
| 87 | 
            +
                let(:config) { super().merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}, {"host" => "tcp:snmp1/161", "community" => "public"}]})}
         | 
| 88 | 
            +
                it "should return two events " do
         | 
| 89 | 
            +
                  plugin.register
         | 
| 90 | 
            +
                  queue = []
         | 
| 91 | 
            +
                  stop_plugin_after_seconds(plugin)
         | 
| 92 | 
            +
                  plugin.run(queue)
         | 
| 93 | 
            +
                  plugin.close
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  host_cnt_snmp1 = queue.select {|event| event.get("host") == "snmp1"}.size
         | 
| 96 | 
            +
                  expect(queue.size).to eq(2)
         | 
| 97 | 
            +
                  expect(host_cnt_snmp1).to eq(2)
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
              describe "single input plugin on multiple udp hosts", :integration => true do
         | 
| 102 | 
            +
                let(:config) { super().merge({"hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}, {"host" => "udp:snmp2/162", "community" => "public"}]})}
         | 
| 103 | 
            +
                it "should return two events, one per host" do
         | 
| 104 | 
            +
                  plugin.register
         | 
| 105 | 
            +
                  queue = []
         | 
| 106 | 
            +
                  stop_plugin_after_seconds(plugin)
         | 
| 107 | 
            +
                  plugin.run(queue)
         | 
| 108 | 
            +
                  plugin.close
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  hosts = queue.map { |event| event.get("host") }.sort
         | 
| 111 | 
            +
                  expect(queue.size).to eq(2)
         | 
| 112 | 
            +
                  expect(hosts).to eq(["snmp1", "snmp2"])
         | 
| 113 | 
            +
                end
         | 
| 114 | 
            +
              end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
              describe "multiple pipelines and mix of udp tcp hosts", :integration => true do
         | 
| 117 | 
            +
                let(:config) { {"get" => ["1.3.6.1.2.1.1.1.0"], "hosts" => [{"host" => "udp:snmp1/161", "community" => "public"}]} }
         | 
| 118 | 
            +
                let(:config2) { {"get" => ["1.3.6.1.2.1.1.1.0"], "hosts" => [{"host" => "tcp:snmp2/162", "community" => "public"}]} }
         | 
| 119 | 
            +
                let(:plugin) { LogStash::Inputs::Snmp.new(config)}
         | 
| 120 | 
            +
                let(:plugin2) { LogStash::Inputs::Snmp.new(config2)}
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                it "should return two events, one per host" do
         | 
| 123 | 
            +
                  plugin.register
         | 
| 124 | 
            +
                  plugin2.register
         | 
| 125 | 
            +
                  queue = []
         | 
| 126 | 
            +
                  queue2 = []
         | 
| 127 | 
            +
                  t = Thread.new {
         | 
| 128 | 
            +
                    stop_plugin_after_seconds(plugin)
         | 
| 129 | 
            +
                    plugin.run(queue)
         | 
| 130 | 
            +
                  }
         | 
| 131 | 
            +
                  t2 = Thread.new {
         | 
| 132 | 
            +
                    stop_plugin_after_seconds(plugin2)
         | 
| 133 | 
            +
                    plugin2.run(queue2)
         | 
| 134 | 
            +
                  }
         | 
| 135 | 
            +
                  t.join(2100)
         | 
| 136 | 
            +
                  t2.join(2100)
         | 
| 137 | 
            +
                  plugin.close
         | 
| 138 | 
            +
                  plugin2.close
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  hosts = [queue.pop, queue2.pop].map { |event| event.get("host") }.sort
         | 
| 141 | 
            +
                  expect(hosts).to eq(["snmp1", "snmp2"])
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
              end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
              describe "multiple plugin inputs and mix of udp tcp hosts", :integration => true do
         | 
| 146 | 
            +
                config = <<-CONFIG
         | 
| 147 | 
            +
                    input {
         | 
| 148 | 
            +
                      snmp {
         | 
| 149 | 
            +
                        get => ["1.3.6.1.2.1.1.1.0"]
         | 
| 150 | 
            +
                        hosts => [{host => "udp:snmp1/161" community => "public"}]
         | 
| 151 | 
            +
                      }
         | 
| 152 | 
            +
                      snmp {
         | 
| 153 | 
            +
                        get => ["1.3.6.1.2.1.1.1.0"]
         | 
| 154 | 
            +
                        hosts => [{host => "tcp:snmp2/162" community => "public"}]
         | 
| 155 | 
            +
                      }
         | 
| 156 | 
            +
                    }
         | 
| 157 | 
            +
                CONFIG
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                it_behaves_like "snmp plugin return one udp event and one tcp event", config
         | 
| 160 | 
            +
              end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
              describe "two plugins on different hosts with snmpv3 with same security name with different credentials and mix of udp and tcp", :integration => true do
         | 
| 163 | 
            +
                config = <<-CONFIG
         | 
| 164 | 
            +
                    input {
         | 
| 165 | 
            +
                      snmp {
         | 
| 166 | 
            +
                        get => ["1.3.6.1.2.1.1.1.0"]
         | 
| 167 | 
            +
                        hosts => [{host => "udp:snmp1/161" version => "3"}]
         | 
| 168 | 
            +
                        security_name => "user_1"
         | 
| 169 | 
            +
                        auth_protocol => "sha"
         | 
| 170 | 
            +
                        auth_pass => "STrP@SSPhr@sE"
         | 
| 171 | 
            +
                        priv_protocol => "aes"
         | 
| 172 | 
            +
                        priv_pass => "STr0ngP@SSWRD161"
         | 
| 173 | 
            +
                        security_level => "authPriv"
         | 
| 174 | 
            +
                      }
         | 
| 175 | 
            +
                      snmp {
         | 
| 176 | 
            +
                        get => ["1.3.6.1.2.1.1.1.0"]
         | 
| 177 | 
            +
                        hosts => [{host => "tcp:snmp2/162" version => "3"}]
         | 
| 178 | 
            +
                        security_name => "user_1"
         | 
| 179 | 
            +
                        auth_protocol => "sha"
         | 
| 180 | 
            +
                        auth_pass => "STrP@SSPhr@sE"
         | 
| 181 | 
            +
                        priv_protocol => "aes"
         | 
| 182 | 
            +
                        priv_pass => "STr0ngP@SSWRD162"
         | 
| 183 | 
            +
                        security_level => "authPriv"
         | 
| 184 | 
            +
                      }
         | 
| 185 | 
            +
                    }
         | 
| 186 | 
            +
                CONFIG
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                it_behaves_like "snmp plugin return one udp event and one tcp event", config
         | 
| 189 | 
            +
              end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
              describe "single host with tcp over ipv6", :integration => true do
         | 
| 192 | 
            +
                let(:config) { super().merge({"hosts" => [{"host" => "tcp:[2001:3984:3989::161]/161"}]})}
         | 
| 193 | 
            +
                it_behaves_like "snmp plugin return single event"
         | 
| 194 | 
            +
              end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
              def stop_plugin_after_seconds(plugin)
         | 
| 197 | 
            +
                  Thread.new{
         | 
| 198 | 
            +
                    sleep(2)
         | 
| 199 | 
            +
                    plugin.do_stop
         | 
| 200 | 
            +
                  }
         | 
| 201 | 
            +
              end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
            end
         | 
| 
            File without changes
         | 
    
        data/spec/inputs/snmp_spec.rb
    CHANGED
    
    | @@ -171,5 +171,95 @@ describe LogStash::Inputs::Snmp do | |
| 171 171 | 
             
                  expect(event.get("host")).to eq("udp:127.0.0.1/161,public")
         | 
| 172 172 | 
             
                end
         | 
| 173 173 | 
             
              end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
              context "StoppableIntervalRunner" do
         | 
| 176 | 
            +
                let(:stop_holder) { Struct.new(:value).new(false) }
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                before(:each) do
         | 
| 179 | 
            +
                  allow(plugin).to receive(:stop?) { stop_holder.value }
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                let(:plugin) do
         | 
| 183 | 
            +
                  double("Plugin").tap do |dbl|
         | 
| 184 | 
            +
                    allow(dbl).to receive(:logger).and_return(double("Logger").as_null_object)
         | 
| 185 | 
            +
                    allow(dbl).to receive(:stop?) { stop_holder.value }
         | 
| 186 | 
            +
                  end
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                subject(:interval_runner) { LogStash::Inputs::Snmp::StoppableIntervalRunner.new(plugin) }
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                context "#every" do
         | 
| 192 | 
            +
                  context "when the plugin is stopped" do
         | 
| 193 | 
            +
                    let(:interval_seconds) { 2 }
         | 
| 194 | 
            +
                    it 'does not yield the block' do
         | 
| 195 | 
            +
                      stop_holder.value = true
         | 
| 196 | 
            +
                      expect { |yielder| interval_runner.every(interval_seconds, &yielder) }.to_not yield_control
         | 
| 197 | 
            +
                    end
         | 
| 198 | 
            +
                  end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                  context "when the yield takes shorter than the interval" do
         | 
| 201 | 
            +
                    let(:duration_seconds) { 1 }
         | 
| 202 | 
            +
                    let(:interval_seconds) { 2 }
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                    it 'sleeps off the remainder' do
         | 
| 205 | 
            +
                      allow(interval_runner).to receive(:sleep).and_call_original
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                      interval_runner.every(interval_seconds) do
         | 
| 208 | 
            +
                        Kernel::sleep(duration_seconds) # non-stoppable
         | 
| 209 | 
            +
                        stop_holder.value = true # prevent re-runs
         | 
| 210 | 
            +
                      end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                      expect(interval_runner).to have_received(:sleep).with(a_value_within(0.1).of(1))
         | 
| 213 | 
            +
                    end
         | 
| 214 | 
            +
                  end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                  context "when the yield takes longer than the interval" do
         | 
| 217 | 
            +
                    let(:duration_seconds) { 2 }
         | 
| 218 | 
            +
                    let(:interval_seconds) { 1 }
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                    it 'logs a warning to the plugin' do
         | 
| 221 | 
            +
                      allow(interval_runner).to receive(:sleep).and_call_original
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                      interval_runner.every(interval_seconds) do
         | 
| 224 | 
            +
                        Kernel::sleep(duration_seconds) # non-stoppable
         | 
| 225 | 
            +
                        stop_holder.value = true # prevent re-runs
         | 
| 226 | 
            +
                      end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                      expect(interval_runner).to_not have_received(:sleep)
         | 
| 229 | 
            +
             | 
| 230 | 
            +
                      expect(plugin.logger).to have_received(:warn).with(a_string_including("took longer"), a_hash_including(:interval_seconds => interval_seconds, :duration_seconds => a_value_within(0.1).of(duration_seconds)))
         | 
| 231 | 
            +
                    end
         | 
| 232 | 
            +
                  end
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                  it 'runs regularly until the plugin is stopped' do
         | 
| 235 | 
            +
                    timestamps = []
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                    thread = Thread.new do
         | 
| 238 | 
            +
                      interval_runner.every(1) do
         | 
| 239 | 
            +
                        timestamps << Time.now
         | 
| 240 | 
            +
                        Kernel::sleep(Random::rand(0.8))
         | 
| 241 | 
            +
                      end
         | 
| 242 | 
            +
                    end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                    Kernel::sleep(5)
         | 
| 245 | 
            +
                    expect(thread).to be_alive
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                    stop_holder.value = true
         | 
| 248 | 
            +
                    Kernel::sleep(1)
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                    aggregate_failures do
         | 
| 251 | 
            +
                      expect(thread).to_not be_alive
         | 
| 252 | 
            +
                      expect(timestamps.count).to be_within(1).of(5)
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                      timestamps.each_cons(2) do |previous, current|
         | 
| 255 | 
            +
                        # ensure each start time is very close to 1s after the previous.
         | 
| 256 | 
            +
                        expect(current - previous).to be_within(0.05).of(1)
         | 
| 257 | 
            +
                      end
         | 
| 258 | 
            +
             | 
| 259 | 
            +
                      thread.kill if thread.alive?
         | 
| 260 | 
            +
                    end
         | 
| 261 | 
            +
                  end
         | 
| 262 | 
            +
                end
         | 
| 263 | 
            +
              end
         | 
| 174 264 | 
             
            end
         | 
| 175 265 |  | 
| Binary file | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: logstash-input-snmp
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.2. | 
| 4 | 
            +
              version: 1.2.8
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Elasticsearch
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2021-09-15 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -414,9 +414,12 @@ files: | |
| 414 414 | 
             
            - logstash-input-snmp.gemspec
         | 
| 415 415 | 
             
            - spec/fixtures/RFC1213-MIB.dic
         | 
| 416 416 | 
             
            - spec/fixtures/collision.dic
         | 
| 417 | 
            +
            - spec/inputs/integration/it_spec.rb
         | 
| 417 418 | 
             
            - spec/inputs/snmp/base_client_spec.rb
         | 
| 419 | 
            +
            - spec/inputs/snmp/interval_runner_spec.rb
         | 
| 418 420 | 
             
            - spec/inputs/snmp/mib_spec.rb
         | 
| 419 421 | 
             
            - spec/inputs/snmp_spec.rb
         | 
| 422 | 
            +
            - vendor/jar-dependencies/org/snmp4j/snmp4j/2.5.11/snmp4j-2.5.11.jar
         | 
| 420 423 | 
             
            - vendor/jar-dependencies/org/snmp4j/snmp4j/2.8.4/snmp4j-2.8.4.jar
         | 
| 421 424 | 
             
            homepage: http://www.elastic.co/guide/en/logstash/current/index.html
         | 
| 422 425 | 
             
            licenses:
         | 
| @@ -440,14 +443,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 440 443 | 
             
                - !ruby/object:Gem::Version
         | 
| 441 444 | 
             
                  version: '0'
         | 
| 442 445 | 
             
            requirements: []
         | 
| 443 | 
            -
             | 
| 444 | 
            -
            rubygems_version: 2.6.13
         | 
| 446 | 
            +
            rubygems_version: 3.1.6
         | 
| 445 447 | 
             
            signing_key:
         | 
| 446 448 | 
             
            specification_version: 4
         | 
| 447 449 | 
             
            summary: SNMP input plugin
         | 
| 448 450 | 
             
            test_files:
         | 
| 449 451 | 
             
            - spec/fixtures/RFC1213-MIB.dic
         | 
| 450 452 | 
             
            - spec/fixtures/collision.dic
         | 
| 453 | 
            +
            - spec/inputs/integration/it_spec.rb
         | 
| 451 454 | 
             
            - spec/inputs/snmp/base_client_spec.rb
         | 
| 455 | 
            +
            - spec/inputs/snmp/interval_runner_spec.rb
         | 
| 452 456 | 
             
            - spec/inputs/snmp/mib_spec.rb
         | 
| 453 457 | 
             
            - spec/inputs/snmp_spec.rb
         |