From 04aa32cd576ef47a7ec1b7a2df4f5f60b8b9a6bd Mon Sep 17 00:00:00 2001 From: Lehel Date: Thu, 26 May 2022 18:35:14 +0200 Subject: [PATCH] NIFI-10054: Improve SendTrapSNMP error handling Signed-off-by: Pierre Villard This closes #6081. --- .../snmp/operations/SendTrapSNMPHandler.java | 10 ++++- .../operations/SendTrapSNMPHandlerTest.java | 41 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java index f9f608d670..6b2a3bfc2a 100644 --- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java +++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java @@ -25,6 +25,8 @@ import org.apache.nifi.snmp.utils.SNMPUtils; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; +import org.snmp4j.event.ResponseEvent; +import org.snmp4j.smi.TransportIpAddress; import java.io.IOException; import java.time.Instant; @@ -62,7 +64,13 @@ public class SendTrapSNMPHandler { logger.debug("No optional SNMP specific variables found in flowfile."); } - snmpManager.send(pdu, target); + final ResponseEvent response = snmpManager.send(pdu, target); + if (response == null) { + final int port = ((TransportIpAddress) target.getAddress()).getPort(); + throw new IOException(String.format("The sent PDU has not been confirmed, the target port [%d] may be unavailable.", port)); + } else if (response.getError() != null) { + throw new IOException("An error occurred while sending trap.", response.getError()); + } } V1TrapPDUFactory createV1TrapPduFactory(final Instant startTime) { diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java index 6a202055f4..b7bed1d682 100644 --- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java +++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java @@ -18,6 +18,7 @@ package org.apache.nifi.snmp.operations; import org.apache.nifi.snmp.configuration.V1TrapConfiguration; import org.apache.nifi.snmp.configuration.V2TrapConfiguration; +import org.apache.nifi.snmp.exception.SNMPException; import org.apache.nifi.snmp.factory.trap.V1TrapPDUFactory; import org.apache.nifi.snmp.factory.trap.V2TrapPDUFactory; import org.apache.nifi.util.MockComponentLog; @@ -27,12 +28,16 @@ import org.junit.Test; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; +import org.snmp4j.event.ResponseEvent; +import org.snmp4j.smi.TransportIpAddress; import java.io.IOException; import java.time.Instant; import java.util.Collections; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -42,6 +47,7 @@ public class SendTrapSNMPHandlerTest { private Target mockTarget; private Snmp mockSnmpManager; private PDU mockPdu; + private ResponseEvent mockResponseEvent; private MockComponentLog mockComponentLog; private V1TrapConfiguration mockV1TrapConfiguration; private V2TrapConfiguration mockV2TrapConfiguration; @@ -49,10 +55,11 @@ public class SendTrapSNMPHandlerTest { private SendTrapSNMPHandler sendTrapSNMPHandler; @Before - public void init() { + public void init() throws IOException { mockTarget = mock(Target.class); mockSnmpManager = mock(Snmp.class); mockPdu = mock(PDU.class); + mockResponseEvent = mock(ResponseEvent.class); mockComponentLog = new MockComponentLog("id", new Object()); mockV1TrapConfiguration = mock(V1TrapConfiguration.class); mockV2TrapConfiguration = mock(V2TrapConfiguration.class); @@ -61,6 +68,8 @@ public class SendTrapSNMPHandlerTest { V2TrapPDUFactory mockV2TrapPDUFactory = mock(V2TrapPDUFactory.class); when(mockV2TrapPDUFactory.get(mockV2TrapConfiguration)).thenReturn(mockPdu); + when(mockSnmpManager.send(mockPdu, mockTarget)).thenReturn(mockResponseEvent); + snmpResourceHandler = new SNMPResourceHandler(mockSnmpManager, mockTarget); sendTrapSNMPHandler = new SendTrapSNMPHandler(snmpResourceHandler, Instant.now(), mockComponentLog) { @@ -106,4 +115,34 @@ public class SendTrapSNMPHandlerTest { final String expectedDebugLog = "{} No optional SNMP specific variables found in flowfile."; assertEquals(expectedDebugLog, mockComponentLog.getDebugMessages().get(0).getMsg()); } + + @Test + public void testSendTrapToInvalidPort() throws IOException { + when(mockSnmpManager.send(mockPdu, mockTarget)).thenReturn(null); + final TransportIpAddress mockAddress = mock(TransportIpAddress.class); + final int port = 55555; + when(mockAddress.getPort()).thenReturn(port); + when(mockTarget.getAddress()).thenReturn(mockAddress); + + final String flowFileOid = "1.3.6.1.2.1.1.1.0"; + Exception e = assertThrows(IOException.class, + () -> sendTrapSNMPHandler.sendTrap(Collections.singletonMap("snmp$" + flowFileOid, "OID value"), mockV2TrapConfiguration) + ); + + assertTrue(e.getMessage().contains(String.valueOf(port))); + } + + @Test + public void testSendTrapInvalidResponse() throws IOException { + final String trapSnmpError = "Test Trap SNMP Error"; + when(mockResponseEvent.getError()).thenReturn(new SNMPException(trapSnmpError)); + when(mockSnmpManager.send(mockPdu, mockTarget)).thenReturn(mockResponseEvent); + + final String flowFileOid = "1.3.6.1.2.1.1.1.0"; + Exception e = assertThrows(IOException.class, + () -> sendTrapSNMPHandler.sendTrap(Collections.singletonMap("snmp$" + flowFileOid, "OID value"), mockV2TrapConfiguration) + ); + + assertTrue(e.getCause().getMessage().contains(trapSnmpError)); + } }