Repository: Azure/WALinuxAgent

Issue:
ExtensionsConfig May Not Contain a failoverLocation Attribute
The agent expects ExtensionsConfig to have a location and failoverLocation for each plugin.  This has been proven to not be true for all regions.  I consider this to be a bug upstream, but the agent should be robust enough to handle this case.


Discussion:
boumenot: I opened #1161 to address the telemetry issue.  There is some sort of circular dependency issue that manifest on CI, but not locally.  I will debug it later, and add the necessary event.

Patch:
diff --git a/azurelinuxagent/common/protocol/wire.py b/azurelinuxagent/common/protocol/wire.py
index 841f9b72..265b1f6f 100644
--- a/azurelinuxagent/common/protocol/wire.py
+++ b/azurelinuxagent/common/protocol/wire.py
@@ -600,6 +600,12 @@ class WireClient(object):
         random.shuffle(version_uris_shuffled)
 
         for version in version_uris_shuffled:
+            # GA expects a location and failoverLocation in ExtensionsConfig, but
+            # this is not always the case. See #1147.
+            if version.uri is None:
+                logger.verbose('The specified manifest URL is empty, ignored.')
+                continue
+
             response = None
             if not HostPluginProtocol.is_default_channel():
                 response = self.fetch(version.uri)
diff --git a/azurelinuxagent/common/utils/restutil.py b/azurelinuxagent/common/utils/restutil.py
index 5ceb4c94..fc9aac93 100644
--- a/azurelinuxagent/common/utils/restutil.py
+++ b/azurelinuxagent/common/utils/restutil.py
@@ -170,8 +170,6 @@ def _http_request(method, host, rel_uri, port=None, data=None, secure=False,
                   headers=None, proxy_host=None, proxy_port=None):
 
     headers = {} if headers is None else headers
-    headers['Connection'] = 'close'
-
     use_proxy = proxy_host is not None and proxy_port is not None
 
     if port is None:


Test patch:
diff --git a/tests/utils/test_rest_util.py b/tests/utils/test_rest_util.py
index adeb8141..a864884a 100644
--- a/tests/utils/test_rest_util.py
+++ b/tests/utils/test_rest_util.py
@@ -195,7 +195,7 @@ class TestHttpOperations(AgentTestCase):
         ])
         HTTPSConnection.assert_not_called()
         mock_conn.request.assert_has_calls([
-            call(method="GET", url="/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT, 'Connection': 'close'})
+            call(method="GET", url="/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT})
         ])
         self.assertEqual(1, mock_conn.getresponse.call_count)
         self.assertNotEquals(None, resp)
@@ -218,7 +218,7 @@ class TestHttpOperations(AgentTestCase):
             call("foo", 443, timeout=10)
         ])
         mock_conn.request.assert_has_calls([
-            call(method="GET", url="/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT, 'Connection': 'close'})
+            call(method="GET", url="/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT})
         ])
         self.assertEqual(1, mock_conn.getresponse.call_count)
         self.assertNotEquals(None, resp)
@@ -242,7 +242,7 @@ class TestHttpOperations(AgentTestCase):
         ])
         HTTPSConnection.assert_not_called()
         mock_conn.request.assert_has_calls([
-            call(method="GET", url="http://foo:80/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT, 'Connection': 'close'})
+            call(method="GET", url="http://foo:80/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT})
         ])
         self.assertEqual(1, mock_conn.getresponse.call_count)
         self.assertNotEquals(None, resp)
@@ -267,7 +267,7 @@ class TestHttpOperations(AgentTestCase):
             call("foo.bar", 23333, timeout=10)
         ])
         mock_conn.request.assert_has_calls([
-            call(method="GET", url="https://foo:443/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT, 'Connection': 'close'})
+            call(method="GET", url="https://foo:443/bar", body=None, headers={'User-Agent': HTTP_USER_AGENT})
         ])
         self.assertEqual(1, mock_conn.getresponse.call_count)
         self.assertNotEquals(None, resp)