BROOKLYN-475: fix machine-details parsing (cherry picked from commit d292e3dbe37dfd7e32c081f755026b230758ca3b)
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/94eb5779 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/94eb5779 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/94eb5779 Branch: refs/heads/0.11.x Commit: 94eb577938394598b8dc4234c1d41a7c773ce262 Parents: 5962374 Author: Aled Sage <[email protected]> Authored: Tue Apr 18 11:35:48 2017 +0100 Committer: Richard Downer <[email protected]> Committed: Tue Apr 18 13:37:44 2017 +0100 ---------------------------------------------------------------------- .../core/location/BasicMachineDetails.java | 30 +++++++++++++++-- .../location/MachineDetailsIntegrationTest.java | 2 ++ .../ssh/SshMachineLocationIntegrationTest.java | 7 ++++ .../location/ssh/SshMachineLocationTest.java | 35 ++++++++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/94eb5779/core/src/main/java/org/apache/brooklyn/core/location/BasicMachineDetails.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/location/BasicMachineDetails.java b/core/src/main/java/org/apache/brooklyn/core/location/BasicMachineDetails.java index b0a9bcd..93374c4 100644 --- a/core/src/main/java/org/apache/brooklyn/core/location/BasicMachineDetails.java +++ b/core/src/main/java/org/apache/brooklyn/core/location/BasicMachineDetails.java @@ -22,8 +22,10 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.io.BufferedReader; import java.io.IOException; +import java.util.AbstractMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; @@ -47,6 +49,7 @@ import com.google.common.base.CharMatcher; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Objects; +import com.google.common.base.Optional; import com.google.common.base.Splitter; import com.google.common.base.Throwables; import com.google.common.collect.Maps; @@ -146,10 +149,20 @@ public class BasicMachineDetails implements MachineDetails { LOG.debug("Found following details at {}: {}", location, stdout); } - Map<String,String> details = Maps.newHashMap(Splitter.on(CharMatcher.anyOf("\r\n")) + // See https://issues.apache.org/jira/browse/BROOKLYN-475: + // If using splitter.withKeyValueSeparator, it fails with "Chunk ... is not a valid entry" + // if a line contains more than one ":"; therefore filter those out ourselves. + Iterable<String> lines = Splitter.on(CharMatcher.anyOf("\r\n")) .omitEmptyStrings() - .withKeyValueSeparator(":") - .split(stdout)); + .split(stdout); + + Map<String, String> details = Maps.newHashMap(); + for (String line : lines) { + Optional<Entry<String, String>> detail = splitLine(line, ":"); + if (detail.isPresent()) { + details.put(detail.get().getKey(), detail.get().getValue()); + } + } String name = details.remove("name"); String version = details.remove("version"); @@ -177,6 +190,17 @@ public class BasicMachineDetails implements MachineDetails { return null; } } + + private Optional<Map.Entry<String, String>> splitLine(String sequence, String separator) { + int index = sequence.indexOf(separator); + if (index < 0) { + return Optional.absent(); // ignore + } else { + String key = sequence.substring(0, index).trim(); + String value = sequence.substring(index+1).trim(); + return Optional.<Map.Entry<String, String>>of(new AbstractMap.SimpleEntry<>(key, value)); + } + } }; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/94eb5779/core/src/test/java/org/apache/brooklyn/core/location/MachineDetailsIntegrationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/location/MachineDetailsIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/location/MachineDetailsIntegrationTest.java index e54cb08..c2994f8 100644 --- a/core/src/test/java/org/apache/brooklyn/core/location/MachineDetailsIntegrationTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/location/MachineDetailsIntegrationTest.java @@ -41,6 +41,8 @@ import org.testng.annotations.Test; public class MachineDetailsIntegrationTest { + // See SshMachineLocationTest.testGetMachineDetails for an equivalent unit test + private static final Logger LOG = LoggerFactory.getLogger(MachineDetailsIntegrationTest.class); TestApplication app; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/94eb5779/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java index 844df4a..c770527 100644 --- a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java +++ b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationIntegrationTest.java @@ -127,6 +127,13 @@ public class SshMachineLocationIntegrationTest extends SshMachineLocationTest { } } + // Overrides and disables super, because real machine won't give extra stdout + @Test(enabled=false) + @Override + public void testGetMachineDetailsWithExtraStdout() throws Exception { + throw new UnsupportedOperationException("Test disabled because real machine does not have extra stdout"); + } + @Test(groups = "Integration") public void testCopyFileTo() throws Exception { File dest = Os.newTempFile(getClass(), ".dest.tmp"); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/94eb5779/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java index bac6018..d2f8645 100644 --- a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java +++ b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java @@ -150,6 +150,41 @@ public class SshMachineLocationTest extends BrooklynAppUnitTestSupport { } @Test + public void testGetMachineDetailsWithExtraStdout() throws Exception { + String response = Joiner.on("\n").join( + "Last login: Fri Apr 14 08:01:37 2017 from 35.156.73.145", + "Line with no colons", + ": colon first", + "colon last:", + "name:MyCentOS", + "version:6.7", + "architecture:x86_64", + "ram:15948", + "cpus:4"); + RecordingSshTool.setCustomResponse(".*uname.*", new CustomResponse(0, response, "")); + + BasicExecutionManager execManager = new BasicExecutionManager("mycontextid"); + BasicExecutionContext execContext = new BasicExecutionContext(execManager); + try { + MachineDetails details = execContext.submit(new Callable<MachineDetails>() { + @Override + public MachineDetails call() { + return host.getMachineDetails(); + }}).get(); + LOG.info("machineDetails="+details); + assertNotNull(details); + + assertEquals(details.getOsDetails().getName(), "MyCentOS", "details="+details); + assertEquals(details.getOsDetails().getVersion(), "6.7", "details="+details); + assertEquals(details.getOsDetails().getArch(), "x86_64", "details="+details); + assertEquals(details.getHardwareDetails().getCpuCount(), Integer.valueOf(4), "details="+details); + assertEquals(details.getHardwareDetails().getRam(), Integer.valueOf(15948), "details="+details); + } finally { + execManager.shutdownNow(); + } + } + + @Test public void testSupplyingMachineDetails() throws Exception { MachineDetails machineDetails = new BasicMachineDetails(new BasicHardwareDetails(1, 1024), new BasicOsDetails("myname", "myarch", "myversion")); SshMachineLocation host2 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
