Repository: Azure/WALinuxAgent
Pull request #1228 (2018-06-22 18:39:08)

Filter out empty artifact profile blobs
```
2018/06/22 07:16:03.677467 ERROR ExtHandler Event: name=WALinuxAgent, op=ArtifactsProfileBlob, message=Content: [<0x00><0x00><0x00><0x00>
```
- add a check for null only content when the blob has not been written yet
- only log telemetry for failures when `log_event` is true
- add unit test for empty strings



Patch:
diff --git a/azurelinuxagent/common/event.py b/azurelinuxagent/common/event.py
index 91615a9e..09117acf 100644
--- a/azurelinuxagent/common/event.py
+++ b/azurelinuxagent/common/event.py
@@ -256,7 +256,7 @@ class EventLogger(object):
                   is_internal=False,
                   log_event=True):
 
-        if not is_success or log_event:
+        if (not is_success) and log_event:
             _log_event(name, op, message, duration, is_success=is_success)
 
         self._add_event(duration, evt_type, is_internal, is_success, message, name, op, version, eventId=1)
@@ -347,13 +347,14 @@ def elapsed_milliseconds(utc_start):
                     (d.microseconds / 1000.0))
 
 
-def report_event(op, is_success=True, message=''):
+def report_event(op, is_success=True, message='', log_event=True):
     from azurelinuxagent.common.version import AGENT_NAME, CURRENT_VERSION
     add_event(AGENT_NAME,
               version=CURRENT_VERSION,
               is_success=is_success,
               message=message,
-              op=op)
+              op=op,
+              log_event=log_event)
 
 
 def report_periodic(delta, op, is_success=True, message=''):
diff --git a/azurelinuxagent/common/protocol/wire.py b/azurelinuxagent/common/protocol/wire.py
index 6e732f60..b81e1451 100644
--- a/azurelinuxagent/common/protocol/wire.py
+++ b/azurelinuxagent/common/protocol/wire.py
@@ -1178,7 +1178,7 @@ class WireClient(object):
                         uri, headers = host.get_artifact_request(blob)
                         profile = self.fetch(uri, headers, use_proxy=False)
 
-                    if not textutil.is_str_none_or_whitespace(profile):
+                    if not textutil.is_str_empty(profile):
                         logger.verbose("Artifacts profile downloaded")
                         try:
                             artifacts_profile = InVMArtifactsProfile(profile)
@@ -1190,7 +1190,8 @@ class WireClient(object):
                             from azurelinuxagent.common.event import report_event, WALAEventOperation
                             report_event(op=WALAEventOperation.ArtifactsProfileBlob,
                                          is_success=False,
-                                         message=msg)
+                                         message=msg,
+                                         log_event=False)
 
                 return artifacts_profile
 
@@ -1669,7 +1670,7 @@ class InVMArtifactsProfile(object):
     * encryptedApplicationProfile (optional)
     """
     def __init__(self, artifacts_profile):
-        if not textutil.is_str_none_or_whitespace(artifacts_profile):
+        if not textutil.is_str_empty(artifacts_profile):
             self.__dict__.update(parse_json(artifacts_profile))
 
     def is_on_hold(self):
diff --git a/azurelinuxagent/common/utils/textutil.py b/azurelinuxagent/common/utils/textutil.py
index 0e92b548..6776d866 100644
--- a/azurelinuxagent/common/utils/textutil.py
+++ b/azurelinuxagent/common/utils/textutil.py
@@ -357,7 +357,7 @@ def parse_json(json_str):
     """
     # trim null and whitespaces
     result = None
-    if not is_str_none_or_whitespace(json_str):
+    if not is_str_empty(json_str):
         import json
         result = json.loads(json_str.rstrip(' \t\r\n\0'))
 
@@ -368,6 +368,10 @@ def is_str_none_or_whitespace(s):
     return s is None or len(s) == 0 or s.isspace()
 
 
+def is_str_empty(s):
+    return is_str_none_or_whitespace(s) or is_str_none_or_whitespace(s.rstrip(' \t\r\n\0'))
+
+
 def hash_strings(string_list):
     """
     Compute a cryptographic hash of a list of strings


Test patch:
diff --git a/tests/utils/test_text_util.py b/tests/utils/test_text_util.py
index a3c2dfa6..0464b249 100644
--- a/tests/utils/test_text_util.py
+++ b/tests/utils/test_text_util.py
@@ -44,7 +44,7 @@ class TestTextUtil(AgentTestCase):
 
         data = "abcd\xa0e\xf0fghijk\xbblm"
         self.assertEqual("abcdXeXfghijkXlm",
-            textutil.replace_non_ascii(data, replace_char='X'))
+                         textutil.replace_non_ascii(data, replace_char='X'))
 
         self.assertEqual('', textutil.replace_non_ascii(None))
 
@@ -159,6 +159,41 @@ class TestTextUtil(AgentTestCase):
         self.assertEqual(result_from_list, hash_from_string.digest())
         self.assertEqual(hash_from_string.hexdigest(), '6367c48dd193d56ea7b0baad25b19455e529f5ee')
 
+    def test_empty_strings(self):
+        self.assertTrue(textutil.is_str_none_or_whitespace(None))
+        self.assertTrue(textutil.is_str_none_or_whitespace(' '))
+        self.assertTrue(textutil.is_str_none_or_whitespace('\t'))
+        self.assertTrue(textutil.is_str_none_or_whitespace('\n'))
+        self.assertTrue(textutil.is_str_none_or_whitespace(' \t'))
+        self.assertTrue(textutil.is_str_none_or_whitespace(' \r\n'))
+
+        self.assertTrue(textutil.is_str_empty(None))
+        self.assertTrue(textutil.is_str_empty(' '))
+        self.assertTrue(textutil.is_str_empty('\t'))
+        self.assertTrue(textutil.is_str_empty('\n'))
+        self.assertTrue(textutil.is_str_empty(' \t'))
+        self.assertTrue(textutil.is_str_empty(' \r\n'))
+
+        self.assertFalse(textutil.is_str_none_or_whitespace(u' \x01 '))
+        self.assertFalse(textutil.is_str_none_or_whitespace(u'foo'))
+        self.assertFalse(textutil.is_str_none_or_whitespace('bar'))
+
+        self.assertFalse(textutil.is_str_empty(u' \x01 '))
+        self.assertFalse(textutil.is_str_empty(u'foo'))
+        self.assertFalse(textutil.is_str_empty('bar'))
+
+        hex_null_1 = u'\x00'
+        hex_null_2 = u' \x00 '
+
+        self.assertFalse(textutil.is_str_none_or_whitespace(hex_null_1))
+        self.assertFalse(textutil.is_str_none_or_whitespace(hex_null_2))
+
+        self.assertTrue(textutil.is_str_empty(hex_null_1))
+        self.assertTrue(textutil.is_str_empty(hex_null_2))
+
+        self.assertNotEqual(textutil.is_str_none_or_whitespace(hex_null_1), textutil.is_str_empty(hex_null_1))
+        self.assertNotEqual(textutil.is_str_none_or_whitespace(hex_null_2), textutil.is_str_empty(hex_null_2))
+
 
 if __name__ == '__main__':
     unittest.main()