Repository: Azure/WALinuxAgent
Pull request #2437 (2021-12-14 12:48:05)

Add support for writing updateStatus to the status blob if requested version in GS
<!-- DO NOT DELETE THIS TEMPLATE -->

## Description
This PR adds support for writing updateStatus to the status blob if requested version in GS. If not, we don't report anything for the updateStatus.

Issue # <!-- if any -->
<!--
Please add an informative description that covers that changes made by the pull request. 
This checklist is used to make sure that common issues in a pull request are addressed.
This will expedite the process of getting your pull request merged and avoid extra work on your part to fix issues discovered during the review process.
-->

---

### PR information
- [ ] The title of the PR is clear and informative.
- [ ] There are a small number of commits, each of which has an informative message. This means that previously merged commits do not appear in the history of the PR. For information on cleaning up the commits in your pull request, [see this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/cleaning-up-commits.md).
- [ ] If applicable, the PR references the bug/issue that it fixes in the description.
- [ ] New Unit tests were added for the changes made

### Quality of Code and Contribution Guidelines
- [ ] I have read the [contribution guidelines](https://github.com/Azure/WALinuxAgent/blob/master/.github/CONTRIBUTING.md).

codecov[bot]: # [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) Report
> Merging [#2437](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) (b42f274) into [develop](https://codecov.io/gh/Azure/WALinuxAgent/commit/df113e09a3f1324571412f4310223173824348a4?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) (df113e0) will **increase** coverage by `0.08%`.
> The diff coverage is `98.14%`.

[![Impacted file tree graph](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437/graphs/tree.svg?width=650&height=150&src=pr&token=ae90E2KYCw&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure)](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure)

```diff
@@             Coverage Diff             @@
##           develop    #2437      +/-   ##
===========================================
+ Coverage    71.66%   71.75%   +0.08%     
===========================================
  Files          101      101              
  Lines        14818    14866      +48     
  Branches      2348     2356       +8     
===========================================
+ Hits         10620    10667      +47     
  Misses        3718     3718              
- Partials       480      481       +1     
```


| [Impacted Files](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure) | Coverage Δ | |
|---|---|---|
| [azurelinuxagent/ga/update.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-YXp1cmVsaW51eGFnZW50L2dhL3VwZGF0ZS5weQ==) | `89.77% <95.83%> (+0.16%)` | :arrow_up: |
| [azurelinuxagent/common/protocol/restapi.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9wcm90b2NvbC9yZXN0YXBpLnB5) | `96.39% <100.00%> (+0.41%)` | :arrow_up: |
| [azurelinuxagent/common/protocol/wire.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-YXp1cmVsaW51eGFnZW50L2NvbW1vbi9wcm90b2NvbC93aXJlLnB5) | `80.58% <100.00%> (+0.11%)` | :arrow_up: |
| [azurelinuxagent/ga/exthandlers.py](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure#diff-YXp1cmVsaW51eGFnZW50L2dhL2V4dGhhbmRsZXJzLnB5) | `85.75% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure). Last update [df113e0...b42f274](https://codecov.io/gh/Azure/WALinuxAgent/pull/2437?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Azure).


Patch:
diff --git a/azurelinuxagent/common/conf.py b/azurelinuxagent/common/conf.py
index 87c4aaa9..65d07030 100644
--- a/azurelinuxagent/common/conf.py
+++ b/azurelinuxagent/common/conf.py
@@ -137,6 +137,7 @@ __SWITCH_OPTIONS__ = {
     "Debug.CgroupDisableOnProcessCheckFailure": True,
     "Debug.CgroupDisableOnQuotaCheckFailure": True,
     "Debug.EnableFastTrack": True,
+    "Debug.EnableGAVersioning": False
 }
 
 
@@ -595,3 +596,12 @@ def get_normal_upgrade_frequency(conf=__conf__):
     NOTE: This option is experimental and may be removed in later versions of the Agent.
     """
     return conf.get_int("Debug.AutoUpdateNormalFrequency", 24 * 60 * 60)
+
+
+def get_enable_ga_versioning(conf=__conf__):
+    """
+    If True, the agent uses GA Versioning for auto-updating the agent vs automatically auto-updating to the highest version.
+
+    NOTE: This option is experimental and may be removed in later versions of the Agent.
+    """
+    return conf.get_switch("Debug.EnableGAVersioning", False)
diff --git a/azurelinuxagent/common/protocol/extensions_goal_state.py b/azurelinuxagent/common/protocol/extensions_goal_state.py
index 247ae0a2..f9e3c32f 100644
--- a/azurelinuxagent/common/protocol/extensions_goal_state.py
+++ b/azurelinuxagent/common/protocol/extensions_goal_state.py
@@ -115,7 +115,7 @@ class ExtensionsGoalState(object):
 
         def compare_agent_manifests(first, second):
             compare_attributes(first, second, "family")
-            compare_attributes(first, second, "version")
+            compare_attributes(first, second, "requested_version_string")
             compare_attributes(first, second, "uris")
 
         def compare_extensions(first, second):
diff --git a/azurelinuxagent/common/protocol/restapi.py b/azurelinuxagent/common/protocol/restapi.py
index 0fef71d4..82a9abc1 100644
--- a/azurelinuxagent/common/protocol/restapi.py
+++ b/azurelinuxagent/common/protocol/restapi.py
@@ -22,10 +22,14 @@ import time
 
 from azurelinuxagent.common.datacontract import DataContract, DataContractList
 from azurelinuxagent.common.future import ustr
+from azurelinuxagent.common.utils.flexible_version import FlexibleVersion
 from azurelinuxagent.common.utils.textutil import getattrib
 from azurelinuxagent.common.version import DISTRO_VERSION, DISTRO_NAME, CURRENT_VERSION
 
 
+VERSION_0 = "0.0.0.0"
+
+
 class VMInfo(DataContract):
     def __init__(self,
                  subscriptionId=None,
@@ -68,9 +72,21 @@ class VMAgentManifest(object):
     def __init__(self, family, version=None):
         self.family = family
         # This is the Requested version as specified by the Goal State, it defaults to 0.0.0.0 if not specified in GS
-        self.version = "0.0.0.0" if version is None else version
+        self.requested_version_string = VERSION_0 if version is None else version
         self.uris = []
 
+    @property
+    def requested_version(self):
+        return FlexibleVersion(self.requested_version_string)
+
+    @property
+    def is_requested_version_specified(self):
+        """
+        If we don't get any requested_version from the GS, we default it to 0.0.0.0.
+        This property identifies if a requested Version was passed in the GS or not.
+        """
+        return self.requested_version > FlexibleVersion(VERSION_0)
+
     def __repr__(self):
         return self.__str__()
 
@@ -267,7 +283,7 @@ class ExtHandlerStatus(DataContract):
 
 
 class VMAgentStatus(DataContract):
-    def __init__(self, status=None, message=None, gs_aggregate_status=None):
+    def __init__(self, status=None, message=None, gs_aggregate_status=None, update_status=None):
         self.status = status
         self.message = message
         self.hostname = socket.gethostname()
@@ -276,11 +292,13 @@ class VMAgentStatus(DataContract):
         self.osversion = DISTRO_VERSION
         self.extensionHandlers = DataContractList(ExtHandlerStatus)
         self.vm_artifacts_aggregate_status = VMArtifactsAggregateStatus(gs_aggregate_status)
+        self.update_status = update_status
 
 
 class VMStatus(DataContract):
-    def __init__(self, status, message, gs_aggregate_status=None):
-        self.vmAgent = VMAgentStatus(status=status, message=message, gs_aggregate_status=gs_aggregate_status)
+    def __init__(self, status, message, gs_aggregate_status=None, vm_agent_update_status=None):
+        self.vmAgent = VMAgentStatus(status=status, message=message, gs_aggregate_status=gs_aggregate_status,
+                                     update_status=vm_agent_update_status)
 
 
 class GoalStateAggregateStatus(DataContract):
@@ -311,3 +329,18 @@ class RemoteAccessUser(DataContract):
 class RemoteAccessUsersList(DataContract):
     def __init__(self):
         self.users = DataContractList(RemoteAccessUser)
+
+
+class VMAgentUpdateStatuses(object):
+    Success = ustr("Success")
+    Transitioning = ustr("Transitioning")
+    Error = ustr("Error")
+    Unknown = ustr("Unknown")
+
+
+class VMAgentUpdateStatus(object):
+    def __init__(self, expected_version, status=VMAgentUpdateStatuses.Success, message="", code=0):
+        self.expected_version = expected_version
+        self.status = status
+        self.message = message
+        self.code = code
diff --git a/azurelinuxagent/common/protocol/wire.py b/azurelinuxagent/common/protocol/wire.py
index 3ca2be1d..99978516 100644
--- a/azurelinuxagent/common/protocol/wire.py
+++ b/azurelinuxagent/common/protocol/wire.py
@@ -292,9 +292,23 @@ def ga_status_to_v1(ga_status):
         "status": ga_status.status,
         "formattedMessage": __get_formatted_msg_for_status_reporting(ga_status.message)
     }
+
+    if ga_status.update_status is not None:
+        v1_ga_status["updateStatus"] = get_ga_update_status_to_v1(ga_status.update_status)
+
     return v1_ga_status
 
 
+def get_ga_update_status_to_v1(update_status):
+    v1_ga_update_status = {
+        "expectedVersion": update_status.expected_version,
+        "status": update_status.status,
+        "code": update_status.code,
+        "formattedMessage": __get_formatted_msg_for_status_reporting(update_status.message)
+    }
+    return v1_ga_update_status
+
+
 def ext_substatus_to_v1(sub_status_list):
     status_list = []
     for substatus in sub_status_list:
diff --git a/azurelinuxagent/ga/exthandlers.py b/azurelinuxagent/ga/exthandlers.py
index 988596f7..c0c23d02 100644
--- a/azurelinuxagent/ga/exthandlers.py
+++ b/azurelinuxagent/ga/exthandlers.py
@@ -889,15 +889,15 @@ class ExtHandlersHandler(object):
 
         return handlers_to_report
 
-    def report_ext_handlers_status(self, incarnation_changed=False):
+    def report_ext_handlers_status(self, incarnation_changed=False, vm_agent_update_status=None):
         """
         Go through handler_state dir, collect and report status.
         Returns the status it reported, or None if an error occurred.
         """
         try:
             vm_status = VMStatus(status="Ready", message="Guest Agent is running",
-                                 gs_aggregate_status=self.__gs_aggregate_status)
-
+                                 gs_aggregate_status=self.__gs_aggregate_status,
+                                 vm_agent_update_status=vm_agent_update_status)
             handlers_to_report = []
 
             # In case of Unsupported error, report the status of the handlers in the VM
diff --git a/azurelinuxagent/ga/update.py b/azurelinuxagent/ga/update.py
index f031b924..6993807c 100644
--- a/azurelinuxagent/ga/update.py
+++ b/azurelinuxagent/ga/update.py
@@ -46,6 +46,7 @@ from azurelinuxagent.common.event import add_event, initialize_event_logger_vmin
 from azurelinuxagent.common.exception import ResourceGoneError, UpdateError, ExitException, AgentUpgradeExitException
 from azurelinuxagent.common.future import ustr
 from azurelinuxagent.common.osutil import get_osutil, systemd
+from azurelinuxagent.common.protocol.restapi import VMAgentUpdateStatus, VMAgentUpdateStatuses
 from azurelinuxagent.common.protocol.util import get_protocol_util
 from azurelinuxagent.common.protocol.hostplugin import HostPluginProtocol
 from azurelinuxagent.common.utils import shellutil
@@ -493,9 +494,54 @@ class UpdateHandler(object):
         finally:
             self.last_incarnation = incarnation
 
+    @staticmethod
+    def __get_vmagent_update_status(protocol, incarnation_changed):
+        """
+        This function gets the VMAgent update status as per the last GoalState.
+        Returns: None if the last GS does not ask for requested version else VMAgentUpdateStatus
+        """
+        if not conf.get_enable_ga_versioning():
+            return None
+
+        update_status = None
+
+        try:
+            agent_manifests, _ = protocol.get_vmagent_manifests()
+
+            try:
+                # Expectation here is that there will only be one manifest per family passed down from CRP
+                # (already verified during validations), we pick the first matching one here.
+                manifest = next(m for m in agent_manifests if m.family == conf.get_autoupdate_gafamily())
+            except StopIteration:
+                if incarnation_changed:
+                    logger.info("Unable to report update status as no matching manifest found for family: {0}".format(
+                        conf.get_autoupdate_gafamily()))
+                return None
+
+            if manifest.is_requested_version_specified:
+                if CURRENT_VERSION == manifest.requested_version:
+                    status = VMAgentUpdateStatuses.Success
+                    code = 0
+                else:
+                    status = VMAgentUpdateStatuses.Error
+                    code = 1
+                update_status = VMAgentUpdateStatus(expected_version=manifest.requested_version_string, status=status,
+                                                    code=code)
+        except Exception as error:
+            if incarnation_changed:
+                err_msg = "[This error will only be logged once per incarnation] " \
+                          "Ran into error when trying to fetch updateStatus for the agent, skipping reporting update satus. Error: {0}".format(
+                           textutil.format_exception(error))
+                logger.warn(err_msg)
+                add_event(op=WALAEventOperation.AgentUpgrade, is_success=False, message=err_msg, log_event=False)
+
+        return update_status
+
     def _report_status(self, exthandlers_handler, incarnation_changed):
+        vm_agent_update_status = self.__get_vmagent_update_status(exthandlers_handler.protocol, incarnation_changed)
         # report_ext_handlers_status does its own error handling and returns None if an error occurred
-        vm_status = exthandlers_handler.report_ext_handlers_status(incarnation_changed=incarnation_changed)
+        vm_status = exthandlers_handler.report_ext_handlers_status(incarnation_changed=incarnation_changed,
+                                                                   vm_agent_update_status=vm_agent_update_status)
         if vm_status is None:
             return
 


Test patch:
diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py
index cf64abde..29e0a76a 100644
--- a/tests/ga/test_update.py
+++ b/tests/ga/test_update.py
@@ -34,7 +34,8 @@ from azurelinuxagent.common.persist_firewall_rules import PersistFirewallRulesHa
 from azurelinuxagent.common.protocol.hostplugin import URI_FORMAT_GET_API_VERSIONS, HOST_PLUGIN_PORT, \
     URI_FORMAT_GET_EXTENSION_ARTIFACT, HostPluginProtocol
 from azurelinuxagent.common.protocol.restapi import VMAgentManifest, \
-    ExtHandlerPackage, ExtHandlerPackageList, Extension, VMStatus, ExtHandlerStatus, ExtensionStatus
+    ExtHandlerPackage, ExtHandlerPackageList, Extension, VMStatus, ExtHandlerStatus, ExtensionStatus, \
+    VMAgentUpdateStatuses
 from azurelinuxagent.common.protocol.util import ProtocolUtil
 from azurelinuxagent.common.protocol.wire import WireProtocol
 from azurelinuxagent.common.utils import fileutil, restutil, textutil
@@ -47,7 +48,7 @@ from azurelinuxagent.ga.update import GuestAgent, GuestAgentError, MAX_FAILURE,
     get_update_handler, ORPHAN_POLL_INTERVAL, AGENT_PARTITION_FILE, AGENT_ERROR_FILE, ORPHAN_WAIT_INTERVAL, \
     CHILD_LAUNCH_RESTART_MAX, CHILD_HEALTH_INTERVAL, GOAL_STATE_PERIOD_EXTENSIONS_DISABLED, UpdateHandler, \
     READONLY_FILE_GLOBS, ExtensionsSummary, AgentUpgradeType
-from tests.protocol.mocks import mock_wire_protocol
+from tests.protocol.mocks import mock_wire_protocol, MockHttpResponse
 from tests.protocol.mockwiredata import DATA_FILE, DATA_FILE_MULTIPLE_EXT
 from tests.tools import AgentTestCase, data_dir, DEFAULT, patch, load_bin_data, Mock, MagicMock, \
     clear_singleton_instances, mock_sleep, skip_if_predicate_true
@@ -1816,6 +1817,67 @@ class TestUpdate(UpdateTestCase):
                 for ext_dir in expected_events_dirs:
                     self.assertTrue(os.path.exists(ext_dir), "Extension directory {0} should exist!".format(ext_dir))
 
+    def test_it_should_report_update_status_in_status_blob(self):
+        with _get_update_handler(iterations=1) as (update_handler, protocol):
+            with patch.object(conf, "get_enable_ga_versioning", return_value=True):
+                with patch.object(conf, "get_autoupdate_gafamily", return_value="Prod"):
+                    with patch("azurelinuxagent.common.logger.warn") as patch_warn:
+
+                        protocol.aggregate_status = None
+                        protocol.incarnation = 1
+
+                        def mock_http_put(url, *args, **_):
+                            if HttpRequestPredicates.is_host_plugin_status_request(url):
+                                # Skip reading the HostGA request data as its encoded
+                                return MockHttpResponse(status=500)
+                            protocol.aggregate_status = json.loads(args[0])
+                            return MockHttpResponse(status=201)
+
+                        def update_goal_state_and_run_handler():
+                            protocol.incarnation += 1
+                            protocol.mock_wire_data.set_incarnation(protocol.incarnation)
+                            self._add_write_permission_to_goal_state_files()
+                            update_handler.set_iterations(1)
+                            update_handler.run(debug=True)
+                            self.assertTrue(update_handler.exit_mock.called, "The process should have exited")
+                            exit_args, _ = update_handler.exit_mock.call_args
+                            self.assertEqual(exit_args[0], 0,
+                                             "Exit code should be 0; List of all warnings logged by the agent: {0}".format(
+                                                 patch_warn.call_args_list))
+
+                        protocol.set_http_handlers(http_put_handler=mock_http_put)
+
+                        # Case 1: No requested version in GS; updateStatus should not be reported
+                        update_goal_state_and_run_handler()
+                        self.assertFalse("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'],
+                                         "updateStatus should not be reported if not asked in GS")
+
+                        # Case 2: Requested version in GS != Current Version; updateStatus should be error
+                        protocol.mock_wire_data.set_extension_config("wire/ext_conf_requested_version.xml")
+                        update_goal_state_and_run_handler()
+                        self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'],
+                                        "updateStatus should be in status blob. Warns: {0}".format(patch_warn.call_args_list))
+                        update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"]
+                        self.assertEqual(VMAgentUpdateStatuses.Error, update_status['status'], "Status should be an error")
+                        self.assertEqual(update_status['expectedVersion'], "9.9.9.10", "incorrect version reported")
+                        self.assertEqual(update_status['code'], 1, "incorrect code reported")
+
+                        # Case 3: Requested version in GS == Current Version; updateStatus should be Success
+                        protocol.mock_wire_data.set_extension_config_requested_version(str(CURRENT_VERSION))
+                        update_goal_state_and_run_handler()
+                        self.assertTrue("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'],
+                                        "updateStatus should be reported if asked in GS")
+                        update_status = protocol.aggregate_status['aggregateStatus']['guestAgentStatus']["updateStatus"]
+                        self.assertEqual(VMAgentUpdateStatuses.Success, update_status['status'], "Status should be successful")
+                        self.assertEqual(update_status['expectedVersion'], str(CURRENT_VERSION), "incorrect version reported")
+                        self.assertEqual(update_status['code'], 0, "incorrect code reported")
+
+                        # Case 4: Requested version removed in GS; no updateStatus should be reported
+                        protocol.mock_wire_data.reload()
+                        update_goal_state_and_run_handler()
+                        self.assertFalse("updateStatus" in protocol.aggregate_status['aggregateStatus']['guestAgentStatus'],
+                                         "updateStatus should not be reported if not asked in GS")
+
 
 class TestAgentUpgrade(UpdateTestCase):
 
diff --git a/tests/protocol/mockwiredata.py b/tests/protocol/mockwiredata.py
index b4acd844..b49f9156 100644
--- a/tests/protocol/mockwiredata.py
+++ b/tests/protocol/mockwiredata.py
@@ -407,3 +407,9 @@ class WireProtocolData(object):
         Sets the version of the extension manifest
         '''
         self.manifest = WireProtocolData.replace_xml_element_value(self.manifest, "Version", version)
+
+    def set_extension_config(self, ext_conf_file):
+        self.ext_conf = load_data(ext_conf_file)
+
+    def set_extension_config_requested_version(self, version):
+        self.ext_conf = WireProtocolData.replace_xml_element_value(self.ext_conf, "Version", version)
diff --git a/tests/protocol/test_extensions_goal_state.py b/tests/protocol/test_extensions_goal_state.py
index 5bddbbce..80469dc5 100644
--- a/tests/protocol/test_extensions_goal_state.py
+++ b/tests/protocol/test_extensions_goal_state.py
@@ -47,7 +47,7 @@ class ExtensionsGoalStateTestCase(AgentTestCase):
             assert_compare_raises(lambda c: setattr(c, "_on_hold",                  False),                     "on_hold")
 
             assert_compare_raises(lambda c: setattr(c.agent_manifests[0], "family",  'MOCK_FAMILY'),  r"agent_manifests[0].family")
-            assert_compare_raises(lambda c: setattr(c.agent_manifests[0], "version", 'MOCK_VERSION'), r"agent_manifests[0].version")
+            assert_compare_raises(lambda c: setattr(c.agent_manifests[0], "requested_version_string", 'MOCK_VERSION'), r"agent_manifests[0].requested_version_string")
             assert_compare_raises(lambda c: setattr(c.agent_manifests[0], "uris",    ['MOCK_URI']),   r"agent_manifests[0].uris")
 
             assert_compare_raises(lambda c: setattr(c.extensions[0], "version",  'MOCK_NAME'),         r"extensions[0].version")
@@ -107,11 +107,11 @@ class ExtensionsGoalStateTestCase(AgentTestCase):
         with mock_wire_protocol(mockwiredata.DATA_FILE) as protocol:
             fabric_manifests, _ = protocol.get_vmagent_manifests()
             for manifest in fabric_manifests:
-                self.assertEqual(manifest.version, "0.0.0.0", "Version should be None")
+                self.assertEqual(manifest.requested_version_string, "0.0.0.0", "Version should be None")
 
             vm_settings_ga_manifests = protocol.client._extensions_goal_state_from_vm_settings.agent_manifests
             for manifest in vm_settings_ga_manifests:
-                self.assertEqual(manifest.version, "0.0.0.0", "Version should be None")
+                self.assertEqual(manifest.requested_version_string, "0.0.0.0", "Version should be None")
 
         data_file = mockwiredata.DATA_FILE.copy()
         data_file["vm_settings"] = "hostgaplugin/vm_settings-requested_version.json"
@@ -119,8 +119,8 @@ class ExtensionsGoalStateTestCase(AgentTestCase):
         with mock_wire_protocol(data_file) as protocol:
             fabric_manifests, _ = protocol.get_vmagent_manifests()
             for manifest in fabric_manifests:
-                self.assertEqual(manifest.version, "9.9.9.10", "Version should be 9.9.9.10")
+                self.assertEqual(manifest.requested_version_string, "9.9.9.10", "Version should be 9.9.9.10")
 
             vm_settings_ga_manifests = protocol.client._extensions_goal_state_from_vm_settings.agent_manifests
             for manifest in vm_settings_ga_manifests:
-                self.assertEqual(manifest.version, "9.9.9.9", "Version should be 9.9.9.9")
+                self.assertEqual(manifest.requested_version_string, "9.9.9.9", "Version should be 9.9.9.9")
diff --git a/tests/test_agent.py b/tests/test_agent.py
index 9d40b697..1ce32129 100644
--- a/tests/test_agent.py
+++ b/tests/test_agent.py
@@ -39,6 +39,7 @@ Debug.CgroupLogMetrics = False
 Debug.CgroupMonitorExpiryTime = 2022-01-31
 Debug.CgroupMonitorExtensionName = Microsoft.Azure.Monitor.AzureMonitorLinuxAgent
 Debug.EnableFastTrack = True
+Debug.EnableGAVersioning = False
 Debug.EtpCollectionPeriod = 300
 DetectScvmmEnv = False
 EnableOverProvisioning = True