Repository: RedHatInsights/insights-core

Issue:
hostname parser doesn't handle sos_commands/general/hostname
sos_commands/general/hostname contains the hostname with a newline at the end, which results in a file with two lines. The hostname parser specifically checks for one line but doesn't gracefully handle the problem.

We can update the parser to handle this case and/or investigate whether proc/sys/kernel/hostname is a valid substitute to put in sos_archive.py instead.


Discussion:
Hi @csams Does this mean that the parser doesn't handles the file with multiline? I verified this by adding few more tests which passed,

```
diff --git a/insights/parsers/tests/test_hostname.py b/insights/parsers/tests/test_hostname.py
index 8b25de81c905..f40e3a8a1d12 100644
--- a/insights/parsers/tests/test_hostname.py
+++ b/insights/parsers/tests/test_hostname.py
@@ -2,7 +2,14 @@ from insights.parsers.hostname import Hostname
 from insights.tests import context_wrap
 
 HOSTNAME = "rhel7.example.com"
+HOSTNAME_MULTILINE = """
+rhel7.example.com
+"""
+
 HOSTNAME_SHORT = "rhel7"
+HOSTNAME_SHORT_MULTILINE = """
+rhel7
+"""
 
 
 def test_hostname():
@@ -12,11 +19,22 @@ def test_hostname():
     assert data.domain == "example.com"
     assert "{0}".format(data) == "<hostname: rhel7, domain: example.com>"
 
+    data = Hostname(context_wrap(HOSTNAME_MULTILINE))
+    assert data.fqdn == "rhel7.example.com"
+    assert data.hostname == "rhel7"
+    assert data.domain == "example.com"
+    assert "{0}".format(data) == "<hostname: rhel7, domain: example.com>"
+
     data = Hostname(context_wrap(HOSTNAME_SHORT))
     assert data.fqdn == "rhel7"
     assert data.hostname == "rhel7"
     assert data.domain == ""
 
+    data = Hostname(context_wrap(HOSTNAME_SHORT_MULTILINE))
+    assert data.fqdn == "rhel7"
+    assert data.hostname == "rhel7"
+    assert data.domain == ""
+
     data = Hostname(context_wrap(""))
     assert data.fqdn is None
     assert data.hostname is None
```

I also created a sosreport to check for extra new line at the end but was not able to find one,

```
[root@dell-r530-28 ~]# cat -e sosreport-dell-r530-28.exampl.com-20180405005618/sos_commands/general/hostname_-f
dell-r530-28.example.com$
[root@dell-r530-28 ~]# cat -e sosreport-dell-r530-28.example.com-20180405005618/sos_commands/general/hostname
dell-r530-28.example.com$
[root@dell-r530-28 ~]# cat -e sosreport-dell-r530-28.example.com-20180405005618/proc/sys/kernel/hostname 
dell-r530-28.example.com$
```

I want to understand this issue.
@psachin Hey, sorry for getting back to you late on this. Since pasting between triple quote strings is common when testing large config files or log snippets, `context_wrap` strips the content you pass it before splitting it into lines:
```
    if isinstance(lines, basestring):
        lines = lines.strip().splitlines()
```
Unfortunately, that's hiding the problem in this particular unit test since it'll strip the newlines.

Also, it looks like not all versions of sos report produce hostname files with the added newline. I have some reports with it and some without it.
@csams That's interesting! That would be older versions of sosreport.

But as you see that new test cases proves that both conditions are handled by parser/context_wrap. It will also give same results while reading multi-line file. Am I missing something?
@psachin context_wrap is hiding the problem because it's stripping the newlines in your new test cases.

Resolving patch:
diff --git a/insights/parsers/hostname.py b/insights/parsers/hostname.py
--- a/insights/parsers/hostname.py
+++ b/insights/parsers/hostname.py
@@ -34,6 +34,7 @@ class Hostname(Parser):
         domain: The domain get from the fqdn.
     """
     def parse_content(self, content):
+        content = filter(None, content)
         raw = None
         if len(content) == 1:
             raw = content[0].strip()


Test patch:
diff --git a/insights/parsers/tests/test_hostname.py b/insights/parsers/tests/test_hostname.py
--- a/insights/parsers/tests/test_hostname.py
+++ b/insights/parsers/tests/test_hostname.py
@@ -2,7 +2,14 @@
 from insights.tests import context_wrap
 
 HOSTNAME = "rhel7.example.com"
+HOSTNAME_MULTILINE = """
+rhel7.example.com
+"""
+
 HOSTNAME_SHORT = "rhel7"
+HOSTNAME_SHORT_MULTILINE = """
+rhel7
+"""
 
 
 def test_hostname():
@@ -12,11 +19,22 @@ def test_hostname():
     assert data.domain == "example.com"
     assert "{0}".format(data) == "<hostname: rhel7, domain: example.com>"
 
+    data = Hostname(context_wrap(HOSTNAME_MULTILINE, strip=False))
+    assert data.fqdn == "rhel7.example.com"
+    assert data.hostname == "rhel7"
+    assert data.domain == "example.com"
+    assert "{0}".format(data) == "<hostname: rhel7, domain: example.com>"
+
     data = Hostname(context_wrap(HOSTNAME_SHORT))
     assert data.fqdn == "rhel7"
     assert data.hostname == "rhel7"
     assert data.domain == ""
 
+    data = Hostname(context_wrap(HOSTNAME_SHORT_MULTILINE, strip=False))
+    assert data.fqdn == "rhel7"
+    assert data.hostname == "rhel7"
+    assert data.domain == ""
+
     data = Hostname(context_wrap(""))
     assert data.fqdn is None
     assert data.hostname is None
diff --git a/insights/tests/__init__.py b/insights/tests/__init__.py
--- a/insights/tests/__init__.py
+++ b/insights/tests/__init__.py
@@ -77,9 +77,12 @@ def context_wrap(lines,
                  release=DEFAULT_RELEASE,
                  version="-1.-1",
                  machine_id="machine_id",
+                 strip=True,
                  **kwargs):
     if isinstance(lines, basestring):
-        lines = lines.strip().splitlines()
+        if strip:
+            lines = lines.strip()
+        lines = lines.splitlines()
     return Context(content=lines,
                    path=path, hostname=hostname,
                    release=release, version=version.split("."),