From 3e66998ab2814ea2b34d4c087bbb9e8dc2d060d2 Mon Sep 17 00:00:00 2001 From: junaidkhan Date: Tue, 19 Nov 2024 18:08:10 +0500 Subject: [PATCH 1/4] NMS:15717 : DeviceConfig via Minion fails if sshScript output contains control characters. --- features/poller/api/pom.xml | 29 ++++++ .../opennms/netmgt/poller/DeviceConfig.java | 2 + .../netmgt/poller/EscapeSequenceAdapter.java | 71 ++++++++++++++ .../poller/EscapeSequenceAdapterTest.java | 98 +++++++++++++++++++ 4 files changed, 200 insertions(+) mode change 100644 => 100755 features/poller/api/pom.xml mode change 100644 => 100755 features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java create mode 100755 features/poller/api/src/main/java/org/opennms/netmgt/poller/EscapeSequenceAdapter.java create mode 100755 features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java diff --git a/features/poller/api/pom.xml b/features/poller/api/pom.xml old mode 100644 new mode 100755 index c230467d2447..ff9f0d59f100 --- a/features/poller/api/pom.xml +++ b/features/poller/api/pom.xml @@ -24,6 +24,17 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + **/*Tests.java + **/*Test.java + + + @@ -45,5 +56,23 @@ hibernate-jpa-2.0-api provided + + org.junit.jupiter + junit-jupiter-api + 5.7.0 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.7.0 + test + + + org.junit.jupiter + junit-jupiter-params + 5.7.0 + test + diff --git a/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java b/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java old mode 100644 new mode 100755 index f46f2c6509e8..ae1a644fc3fc --- a/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java +++ b/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java @@ -32,6 +32,7 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement(name="device-config") @XmlAccessorType(XmlAccessType.NONE) @@ -44,6 +45,7 @@ public class DeviceConfig { private String filename; @XmlAttribute(name="scriptOutput") + @XmlJavaTypeAdapter(EscapeSequenceAdapter.class) private String scriptOutput; public DeviceConfig(String scriptOutput) { diff --git a/features/poller/api/src/main/java/org/opennms/netmgt/poller/EscapeSequenceAdapter.java b/features/poller/api/src/main/java/org/opennms/netmgt/poller/EscapeSequenceAdapter.java new file mode 100755 index 000000000000..a810457fc67c --- /dev/null +++ b/features/poller/api/src/main/java/org/opennms/netmgt/poller/EscapeSequenceAdapter.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * This file is part of OpenNMS(R). + * + * Copyright (C) 2023 The OpenNMS Group, Inc. + * OpenNMS(R) is Copyright (C) 1999-2023 The OpenNMS Group, Inc. + * + * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. + * + * OpenNMS(R) is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * OpenNMS(R) is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with OpenNMS(R). If not, see: + * http://www.gnu.org/licenses/ + * + * For more information contact: + * OpenNMS(R) Licensing + * http://www.opennms.org/ + * http://www.opennms.com/ + *******************************************************************************/ + +package org.opennms.netmgt.poller; + +import org.eclipse.persistence.exceptions.XMLMarshalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +public class EscapeSequenceAdapter extends XmlAdapter { + private static final Logger LOG = LoggerFactory.getLogger(EscapeSequenceAdapter.class); + + public EscapeSequenceAdapter() { + + } + + @Override + public String unmarshal(String v) throws Exception { + if (v != null) { + v = v.replace(" ", "\r") + .replace(" ", "\n"); + } + try { + return v; + } catch (XMLMarshalException e) { + LOG.warn("Unable to unmarshal escape sequences value '{}' to a script output. Returning null instead.", v); + return null; + } + } + + @Override + public String marshal(String v) throws Exception { + if (v != null) { + v = v.replace("\r", " ") + .replace("\n", " "); + } + try { + return v; + } catch (XMLMarshalException e) { + LOG.warn("Unable to marshal escape sequences value '{}' to a script output. Returning null instead.", v); + return null; + } + } +} diff --git a/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java new file mode 100755 index 000000000000..a2dfb4ef1ab4 --- /dev/null +++ b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * This file is part of OpenNMS(R). + * + * Copyright (C) 2023 The OpenNMS Group, Inc. + * OpenNMS(R) is Copyright (C) 1999-2023 The OpenNMS Group, Inc. + * + * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. + * + * OpenNMS(R) is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * OpenNMS(R) is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with OpenNMS(R). If not, see: + * http://www.gnu.org/licenses/ + * + * For more information contact: + * OpenNMS(R) Licensing + * http://www.opennms.org/ + * http://www.opennms.com/ + *******************************************************************************/ + +package org.opennms.netmgt.poller; + + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + + +public class EscapeSequenceAdapterTest { + + private EscapeSequenceAdapter adapter; + + @BeforeEach + public void setUp() { + adapter = new EscapeSequenceAdapter(); + } + + @Test + public void testUnmarshalWithEscapeSequences() throws Exception { + + String input = "Hello World Test"; + String expected = "Hello\rWorld\nTest"; + String result = adapter.unmarshal(input); + assertNotNull(result, "Result should not be null"); + assertEquals(expected, result, "Escape sequences should be replaced correctly"); + } + + @Test + public void testUnmarshalWithNullValue() throws Exception { + String result = adapter.unmarshal(null); + assertNull(result, "Null input should return null"); + } + + @Test + public void testMarshalWithSpecialCharacters() throws Exception { + String input = "Hello\rWorld\nTest"; + String expected = "Hello World Test"; + String result = adapter.marshal(input); + assertNotNull(result, "Result should not be null"); + assertEquals(expected, result, "Special characters should be converted to escape sequences"); + } + + @Test + public void testMarshalWithNullValue() throws Exception { + String result = adapter.marshal(null); + assertNull(result, "Null input should return null"); + } + + @Test + public void testUnmarshalWithNoEscapeSequences() throws Exception { + String input = "NoEscapeSequenceHere"; + String expected = "NoEscapeSequenceHere"; + String result = adapter.unmarshal(input); + assertNotNull(result, "Result should not be null"); + assertEquals(expected, result, "Input without escape sequences should remain unchanged"); + } + + @Test + public void testMarshalWithNoSpecialCharacters() throws Exception { + String input = "NormalString"; + String expected = "NormalString"; + String result = adapter.marshal(input); + assertNotNull(result, "Result should not be null"); + assertEquals(expected, result, "Input without special characters should remain unchanged"); + } + +} From 362eec2a57c28f117a89fc1bd1eb0caa41884afc Mon Sep 17 00:00:00 2001 From: junaidkhan Date: Tue, 19 Nov 2024 22:17:14 +0500 Subject: [PATCH 2/4] [skip ci] --- features/poller/api/pom.xml | 31 +++--------------- .../poller/EscapeSequenceAdapterTest.java | 32 +++++++++---------- 2 files changed, 20 insertions(+), 43 deletions(-) diff --git a/features/poller/api/pom.xml b/features/poller/api/pom.xml index ff9f0d59f100..5fd65ee7d98f 100755 --- a/features/poller/api/pom.xml +++ b/features/poller/api/pom.xml @@ -24,17 +24,6 @@ - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - - **/*Tests.java - **/*Test.java - - - @@ -57,22 +46,10 @@ provided - org.junit.jupiter - junit-jupiter-api - 5.7.0 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.7.0 - test - - - org.junit.jupiter - junit-jupiter-params - 5.7.0 + junit + junit + 4.13.2 test - + \ No newline at end of file diff --git a/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java index a2dfb4ef1ab4..f42bd35e400b 100755 --- a/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java +++ b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java @@ -29,19 +29,20 @@ package org.opennms.netmgt.poller; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertEquals; public class EscapeSequenceAdapterTest { private EscapeSequenceAdapter adapter; - @BeforeEach + @Before public void setUp() { adapter = new EscapeSequenceAdapter(); } @@ -53,13 +54,13 @@ public void testUnmarshalWithEscapeSequences() throws Exception { String expected = "Hello\rWorld\nTest"; String result = adapter.unmarshal(input); assertNotNull(result, "Result should not be null"); - assertEquals(expected, result, "Escape sequences should be replaced correctly"); + assertEquals("Escape sequences should be replaced correctly", expected, result); } @Test public void testUnmarshalWithNullValue() throws Exception { String result = adapter.unmarshal(null); - assertNull(result, "Null input should return null"); + assertNull("Null input should return null", result); } @Test @@ -67,14 +68,14 @@ public void testMarshalWithSpecialCharacters() throws Exception { String input = "Hello\rWorld\nTest"; String expected = "Hello World Test"; String result = adapter.marshal(input); - assertNotNull(result, "Result should not be null"); - assertEquals(expected, result, "Special characters should be converted to escape sequences"); + assertNotNull(result,"Result should not be null"); + assertEquals("Special characters should be converted to escape sequences",expected, result); } @Test public void testMarshalWithNullValue() throws Exception { String result = adapter.marshal(null); - assertNull(result, "Null input should return null"); + assertNull("Null input should return null",result); } @Test @@ -82,8 +83,8 @@ public void testUnmarshalWithNoEscapeSequences() throws Exception { String input = "NoEscapeSequenceHere"; String expected = "NoEscapeSequenceHere"; String result = adapter.unmarshal(input); - assertNotNull(result, "Result should not be null"); - assertEquals(expected, result, "Input without escape sequences should remain unchanged"); + assertNotNull( "Result should not be null",result); + assertEquals("Input without escape sequences should remain unchanged",expected, result); } @Test @@ -91,8 +92,7 @@ public void testMarshalWithNoSpecialCharacters() throws Exception { String input = "NormalString"; String expected = "NormalString"; String result = adapter.marshal(input); - assertNotNull(result, "Result should not be null"); - assertEquals(expected, result, "Input without special characters should remain unchanged"); + assertNotNull( "Result should not be null",result); + assertEquals( "Input without special characters should remain unchanged",expected, result); } - } From 0b9f513fe0ab50ce8bd5be6afc3af2de21e22ddf Mon Sep 17 00:00:00 2001 From: junaidkhan Date: Tue, 19 Nov 2024 22:50:01 +0500 Subject: [PATCH 3/4] NMS-15717 : DeviceConfig via Minion fails if sshScript output contains control characters.(updated). --- .../org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java index f42bd35e400b..7228c69a4b03 100755 --- a/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java +++ b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java @@ -29,7 +29,6 @@ package org.opennms.netmgt.poller; - import org.junit.Before; import org.junit.Test; @@ -49,7 +48,6 @@ public void setUp() { @Test public void testUnmarshalWithEscapeSequences() throws Exception { - String input = "Hello World Test"; String expected = "Hello\rWorld\nTest"; String result = adapter.unmarshal(input); @@ -71,7 +69,6 @@ public void testMarshalWithSpecialCharacters() throws Exception { assertNotNull(result,"Result should not be null"); assertEquals("Special characters should be converted to escape sequences",expected, result); } - @Test public void testMarshalWithNullValue() throws Exception { String result = adapter.marshal(null); From 2537b175c2227441604e14ba44a77b9eeb7f427f Mon Sep 17 00:00:00 2001 From: junaidkhan Date: Wed, 20 Nov 2024 17:05:29 +0500 Subject: [PATCH 4/4] NMS-15717 : DeviceConfig via Minion fails if sshScript output contains control characters.(updated test). --- features/poller/api/pom.xml | 13 +++ .../netmgt/poller/DeviceConfigTest.java | 98 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 features/poller/api/src/test/java/org/opennms/netmgt/poller/DeviceConfigTest.java diff --git a/features/poller/api/pom.xml b/features/poller/api/pom.xml index 5fd65ee7d98f..cff70d4519b2 100755 --- a/features/poller/api/pom.xml +++ b/features/poller/api/pom.xml @@ -51,5 +51,18 @@ 4.13.2 test + + + org.eclipse.persistence + org.eclipse.persistence.core + ${eclipselinkVersion} + test + + + org.eclipse.persistence + org.eclipse.persistence.moxy + ${eclipselinkVersion} + test + \ No newline at end of file diff --git a/features/poller/api/src/test/java/org/opennms/netmgt/poller/DeviceConfigTest.java b/features/poller/api/src/test/java/org/opennms/netmgt/poller/DeviceConfigTest.java new file mode 100644 index 000000000000..ff3fb3c2ae5f --- /dev/null +++ b/features/poller/api/src/test/java/org/opennms/netmgt/poller/DeviceConfigTest.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * This file is part of OpenNMS(R). + * + * Copyright (C) 2023 The OpenNMS Group, Inc. + * OpenNMS(R) is Copyright (C) 1999-2023 The OpenNMS Group, Inc. + * + * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. + * + * OpenNMS(R) is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * OpenNMS(R) is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with OpenNMS(R). If not, see: + * http://www.gnu.org/licenses/ + * + * For more information contact: + * OpenNMS(R) Licensing + * http://www.opennms.org/ + * http://www.opennms.com/ + *******************************************************************************/ + +package org.opennms.netmgt.poller; + +import org.eclipse.persistence.jaxb.JAXBContext; +import org.eclipse.persistence.jaxb.JAXBContextFactory; +import org.junit.Test; + +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import java.io.StringReader; +import java.io.StringWriter; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +public class DeviceConfigTest { + + @Test + public void testMarshalling() throws javax.xml.bind.JAXBException { + String scriptOutput = "HP J8692A Switch 3500yl-24G\r\r\nSoftware revision K.16.02.0026\r\r\n\r\r\n" + + " (C) Copyright 2018 Hewlett Packard Enterprise Development LP\r\n" + + "RESTRICTED RIGHTS LEGEND\r\n Confidential computer software. Valid license from Hewlett Packard Enterprise\r\n" + + "Development LP required for possession, use or copying. Consistent with FAR\r\n" + + "12.211 and 12.212, Commercial Computer Software, Computer Software\r\n" + + "Documentation, and Technical Data for Commercial Items are licensed to the\r\n" + + "U.S. Government under vendor's standard commercial license.\r\n" + + "^[[1;13r^[[1;1H^[[24;1HPress any key to continue\r\n" + + "^[[13;1H^[[?25h^[[24;27H^[[?6l^[[1;24r^[[?7h^[[2J^[[1;1H^[[1920;1920H^[[6n^[[1;1H"; + + DeviceConfig deviceConfig = new DeviceConfig(scriptOutput); + JAXBContext jaxbContext = (JAXBContext) JAXBContextFactory.createContext(new Class[]{DeviceConfig.class}, null); + + Marshaller marshaller = jaxbContext.createMarshaller(); + StringWriter stringWriter = new StringWriter(); + marshaller.marshal(deviceConfig, stringWriter); + String xmlOutput = stringWriter.toString(); + + assertNotNull(xmlOutput); + assertEquals("",xmlOutput); + + } + + @Test + public void testUnmarshalling() throws javax.xml.bind.JAXBException { + + String xmlInput = ""; + + JAXBContext jaxbContext = (JAXBContext) JAXBContextFactory.createContext(new Class[]{DeviceConfig.class}, null); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + + StringReader stringReader = new StringReader(xmlInput); + DeviceConfig deviceConfig = (DeviceConfig) unmarshaller.unmarshal(stringReader); + + String expectedOutputStartWith = "HP J8692A Switch 3500yl-24G\r\r\nSoftware revision K.16.02.0026\r\r\n\r\r\n" + + " (C) Copyright 2018 Hewlett Packard Enterprise Development LP\r\n" ; + String expectedOutputEndWith = "^[[1;13r^[[1;1H^[[24;1HPress any key to continue^[[13;1H^[[?25h^[[24;27H^[[?6l^[[1;24r^[[?7h^[[2J^[[1;1H^[[1920;1920H^[[6n^[[1;1H"; + String expectedOutputMiddleString = "12.211 and 12.212, Commercial Computer Software, Computer Software\r\n" + + "Documentation, and Technical Data for Commercial Items are licensed to the\r\n" ; + + assertNotNull(deviceConfig); + assertTrue(deviceConfig.getScriptOutput().contains(expectedOutputStartWith)); + assertTrue(deviceConfig.getScriptOutput().contains(expectedOutputMiddleString)); + assertTrue(deviceConfig.getScriptOutput().contains(expectedOutputEndWith)); + } +}