diff --git a/azurelinuxagent/common/utils/archive.py b/azurelinuxagent/common/utils/archive.py index c4c83e2f9c..ecd3069b23 100644 --- a/azurelinuxagent/common/utils/archive.py +++ b/azurelinuxagent/common/utils/archive.py @@ -48,10 +48,11 @@ _GOAL_STATE_PATTERN = re.compile(r"^(.*)/GoalState\.(\d+)\.xml$", re.IGNORECASE) +# Old names didn't have incarnation, new ones do. Ensure the regex captures both cases. # 2018-04-06T08:21:37.142697_incarnation_N # 2018-04-06T08:21:37.142697_incarnation_N.zip -_ARCHIVE_PATTERNS_DIRECTORY = re.compile(r"^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d+_incarnation_(\d+)$") -_ARCHIVE_PATTERNS_ZIP = re.compile(r"^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d+_incarnation_(\d+)\.zip$") +_ARCHIVE_PATTERNS_DIRECTORY = re.compile(r"^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d+(_incarnation_(\d+))?$$") +_ARCHIVE_PATTERNS_ZIP = re.compile(r"^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d+(_incarnation_(\d+))?\.zip$") class StateFlusher(object): diff --git a/tests/utils/test_archive.py b/tests/utils/test_archive.py index f128e7da65..818a4ea4b6 100644 --- a/tests/utils/test_archive.py +++ b/tests/utils/test_archive.py @@ -1,16 +1,15 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the Apache License. -from datetime import datetime, timedelta - -import zipfile import os import shutil import tempfile +import zipfile +from datetime import datetime, timedelta import azurelinuxagent.common.logger as logger from azurelinuxagent.common.utils import fileutil from azurelinuxagent.common.utils.archive import StateFlusher, StateArchiver, _MAX_ARCHIVED_STATES -from tests.tools import AgentTestCase +from tests.tools import AgentTestCase, patch debug = False # pylint: disable=invalid-name if os.environ.get('DEBUG') == '1': @@ -50,7 +49,7 @@ def _parse_archive_name(name): # Name can be a directory or a zip # '0000-00-00T00:00:00.000000_incarnation_0' # '0000-00-00T00:00:00.000000_incarnation_0.zip' - timestamp_str, _, incarnation_ext = name.split("_") + timestamp_str, incarnation_ext = name.split("_incarnation_") incarnation_no_ext = os.path.splitext(incarnation_ext)[0] return timestamp_str, incarnation_no_ext @@ -173,6 +172,34 @@ def test_archive02(self): self.assertTrue(filename in archived_entries, "'{0}' is not in the list of unpurged entires".format(filename)) def test_archive03(self): + """ + All archives should be purged, both with the new naming (with incarnation number) and with the old naming. + """ + start = datetime.now() + timestamp1 = start + timedelta(seconds=5) + timestamp2 = start + timedelta(seconds=10) + + dir_old = timestamp1.isoformat() + dir_new = "{0}_incarnation_1".format(timestamp2.isoformat()) + + archive_old = "{0}.zip".format(timestamp1.isoformat()) + archive_new = "{0}_incarnation_1.zip".format(timestamp2.isoformat()) + + self._write_file(os.path.join("history", dir_old, "Prod.0.manifest.xml")) + self._write_file(os.path.join("history", dir_new, "Prod.1.manifest.xml")) + self._write_file(os.path.join("history", archive_old)) + self._write_file(os.path.join("history", archive_new)) + + self.assertEqual(4, len(os.listdir(self.history_dir)), "Not all entries were archived!") + + test_subject = StateArchiver(self.tmp_dir) + with patch("azurelinuxagent.common.utils.archive._MAX_ARCHIVED_STATES", 0): + test_subject.purge() + + archived_entries = os.listdir(self.history_dir) + self.assertEqual(0, len(archived_entries), "Not all entries were purged!") + + def test_archive04(self): """ The archive directory is created if it does not exist.