Skip to content

Commit 3b411bf

Browse files
authored
Version Comparator Comments as Code on PR Branch (#296)
1 parent b68f39d commit 3b411bf

File tree

8 files changed

+128
-330
lines changed

8 files changed

+128
-330
lines changed

src/core/src/bootstrap/Constants.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,3 @@ class BufferMessage(EnumBackport):
382382
TRUE = 0
383383
FALSE = 1
384384
FLUSH = 2
385-
386-
class VersionComparator(EnumBackport):
387-
LINUXPATCHEXTENSION = "LinuxPatchExtension"
388-

src/core/src/core_logic/VersionComparator.py

Lines changed: 10 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,12 @@
1313
# limitations under the License.
1414
#
1515
# Requires Python 2.7+
16-
import os.path
1716
import re
1817

19-
from core.src.bootstrap.Constants import Constants
20-
2118

2219
class VersionComparator(object):
2320

24-
def compare_version_nums(self, version_a, version_b):
21+
def compare_versions(self, version_a, version_b):
2522
# type (str, str) -> int
2623
""" Compare two versions with handling numeric and string parts, return -1 (less), +1 (greater), 0 (equal) """
2724

@@ -38,28 +35,8 @@ def compare_version_nums(self, version_a, version_b):
3835
# If equal 27.13.4 vs 27.13.4, return 0
3936
return (len(parse_version_a) > len(parse_version_b)) - (len(parse_version_a) < len(parse_version_b))
4037

41-
def extract_lpe_path_version_num(self, lpe_path):
42-
# type (str) -> str
43-
"""
44-
Extract the version part from a given lpe path.
45-
Input Extracted Version
46-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25 "1.2.25"
47-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.250 "1.2.250"
48-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.2501 "1.21.2501"
49-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25. "1.2.25"
50-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25.. "1.2.25"
51-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25abc "1.2.25"
52-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25.abc "1.2.25"
53-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25+abc.123 "1.2.25"
54-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25-abc+def.123 "1.2.25"
55-
/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-a.b.c ""
56-
"""
57-
58-
lpe_filename = os.path.basename(lpe_path) # Microsoft.CPlat.Core.LinuxPatchExtension-x.x.xx
59-
lpe_version = re.search(r'(\d+(?:\.\d+)*)', lpe_filename) # extract numbers with optional dot-separated parts
60-
return lpe_version.group(1).rstrip('.') if lpe_version else ""
61-
62-
def extract_os_version_nums(self, os_version):
38+
@staticmethod
39+
def extract_version_from_os_version_nums(os_version):
6340
# type (str) -> str
6441
"""
6542
Extract the version part from a given os version.
@@ -82,59 +59,22 @@ def extract_os_version_nums(self, os_version):
8259
version_num = re.search(r'(\d+(?:\.\d+)*)', os_version) # extract numbers with optional dot-separated parts
8360
return version_num.group(1) if version_num else str()
8461

85-
def sort_versions_desc_order(self, version_list):
86-
# type (list[str]) -> list[str]
87-
"""
88-
Sort paths based on version numbers extracted from paths.
89-
Lpe input:
90-
["/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.1001",
91-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.100",
92-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.100"]
93-
Return:
94-
["/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.1001",
95-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.100",
96-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.100"]
97-
98-
Os Version input:
99-
["32.101~18.01",
100-
"32.101.15~18",
101-
"34~18.04",
102-
"32~18.04.01",
103-
"32.1~18.04.01"]
104-
105-
return:
106-
["34~18.04",
107-
"32.101.15~18",
108-
"32.101~18.01",
109-
"32.1~18.04.01",
110-
"32~18.04.01"]
111-
"""
112-
return sorted(version_list, key=self.__version_key, reverse=True)
113-
11462
def __version_key(self, version_input):
11563
# type (str) -> (int)
11664
""" Extract version number from input and return int tuple.
117-
Lpe input: "/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.100"
118-
Return: (1.6.100)
119-
12065
os version input: "34~18.04"
12166
Return: (34)
12267
"""
123-
if Constants.VersionComparator.LINUXPATCHEXTENSION in version_input:
124-
version_numbers = self.extract_lpe_path_version_num(lpe_path=version_input)
125-
else:
126-
version_numbers = self.extract_os_version_nums(os_version=version_input)
127-
68+
version_numbers = self.extract_version_from_os_version_nums(os_version=version_input)
12869
return tuple(map(int, version_numbers.split('.'))) if version_numbers else (0, 0, 0)
12970

130-
def __split_version_components(self, version):
131-
# type (str) -> [any]
132-
""" Split a version into numeric and non-numeric into components list: 27.13.4~18.04.1 -> [27][14][4]"""
133-
return [int(x) if x.isdigit() else x for x in re.split(r'(\d+)', version) if x]
134-
13571
def __parse_version(self, version_components):
13672
# type (str) -> [[any]]
137-
""" Parse the split version list into list [27][14][4] -> [[27], [14], [4]]"""
73+
""" Parse the split version list into list [27][14][4] -> [[27], [14], [4]] """
13874
return [self.__split_version_components(x) for x in version_components.split(".")]
13975

140-
76+
@staticmethod
77+
def __split_version_components(version):
78+
# type (str) -> [any]
79+
""" Splits a version into numeric and non-numeric into components list: 27.13.4~18.04.1 -> [27][14][4] """
80+
return [int(x) if x.isdigit() else x for x in re.split(r'(\d+)', version) if x]

src/core/src/package_managers/UbuntuProClient.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ def is_pro_working(self):
5757
ubuntu_pro_client_version = version_result.installed_version
5858

5959
# extract version from pro_client_verison 27.13.4~18.04.1 -> 27.13.4
60-
extracted_ubuntu_pro_client_version = self.version_comparator.extract_os_version_nums(ubuntu_pro_client_version)
60+
extracted_ubuntu_pro_client_version = self.version_comparator.extract_version_from_os_version_nums(ubuntu_pro_client_version)
6161

6262
self.composite_logger.log_debug("Ubuntu Pro Client current version: [ClientVersion={0}]".format(str(extracted_ubuntu_pro_client_version)))
6363

6464
# use custom comparator output 0 (equal), -1 (less), +1 (greater)
65-
is_minimum_ubuntu_pro_version_installed = self.version_comparator.compare_version_nums(extracted_ubuntu_pro_client_version, Constants.UbuntuProClientSettings.MINIMUM_CLIENT_VERSION) >= 0
65+
is_minimum_ubuntu_pro_version_installed = self.version_comparator.compare_versions(extracted_ubuntu_pro_client_version, Constants.UbuntuProClientSettings.MINIMUM_CLIENT_VERSION) >= 0
6666

6767
if ubuntu_pro_client_version is not None and is_minimum_ubuntu_pro_version_installed:
6868
is_ubuntu_pro_client_working = True

src/core/tests/Test_VersionComparator.py

Lines changed: 22 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -24,108 +24,34 @@ class TestVersionComparator(unittest.TestCase):
2424
def setUp(self):
2525
self.version_comparator = VersionComparator()
2626

27-
def test_linux_extension_version_extract_comparator(self):
28-
""" Test extract version logic on Extension package """
29-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25"), "1.2.25")
30-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.250"), "1.2.250")
31-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.2501"),
32-
"1.21.2501")
33-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25."), "1.2.25")
34-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25.."), "1.2.25")
35-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25abc"), "1.2.25")
36-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25.abc"), "1.2.25")
37-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25+abc.123"),
38-
"1.2.25")
39-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25-abc+def.123"),
40-
"1.2.25")
41-
self.assertEqual(self.version_comparator.extract_lpe_path_version_num("/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-a.b.c"), "")
42-
43-
def test_linux_lpe_version_comparison(self):
44-
""" Test compare versions logic lpe version with existing vm version """
45-
test_extracted_good_version = self.version_comparator.extract_os_version_nums(
46-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25") # return 1.2.25
47-
48-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_good_version, "1.2.25"), 0) # equal 1.2.25 == 1.2.25
49-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_good_version, "1.2.24"), 1) # greater 1.2.25 > 1.2.24
50-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_good_version, "1.19.25"), -1) # less 1.2.25 < 1.19.25, 19 > 2
51-
52-
test_extracted_bad_version = self.version_comparator.extract_os_version_nums(
53-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-a.b.c") # return ""
54-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_bad_version, "1.2.25"), -1) # less "" != 1.2.25
55-
56-
def test_linux_extension_sort_comparator(self):
57-
""" Test sorting comparator on linux patch extension """
58-
unsorted_lpe_versions = [
59-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25-abc+def.123",
60-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.1001",
61-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.100",
62-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.99",
63-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.100",
64-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25-abc",
65-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.9",
66-
]
67-
68-
expected_sorted_lpe_versions = [
69-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.1001",
70-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.21.100",
71-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.100",
72-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.99",
73-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.6.9",
74-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25-abc+def.123",
75-
"/var/lib/waagent/Microsoft.CPlat.Core.LinuxPatchExtension-1.2.25-abc"
76-
]
77-
78-
# validate sorted lpe versions
79-
self.assertEqual(self.version_comparator.sort_versions_desc_order(unsorted_lpe_versions), expected_sorted_lpe_versions)
80-
81-
def test_linux_os_version_extract_comparator(self):
27+
def test_extract_version_from_os_version_nums(self):
8228
""" Test extract version logic on Ubuntuproclient version """
83-
self.assertEqual(self.version_comparator.extract_os_version_nums("34"), "34")
84-
self.assertEqual(self.version_comparator.extract_os_version_nums("34~18"), "34")
85-
self.assertEqual(self.version_comparator.extract_os_version_nums("34.~18.04"), "34")
86-
self.assertEqual(self.version_comparator.extract_os_version_nums("34.a+18.04.1"), "34")
87-
self.assertEqual(self.version_comparator.extract_os_version_nums("34abc-18.04"), "34")
88-
self.assertEqual(self.version_comparator.extract_os_version_nums("abc34~18.04"), "34")
89-
self.assertEqual(self.version_comparator.extract_os_version_nums("abc34~18.04.123"), "34")
90-
self.assertEqual(self.version_comparator.extract_os_version_nums("34~25.1.2-18.04.1"), "34")
91-
92-
self.assertEqual(self.version_comparator.extract_os_version_nums("34.1~18.04.1"), "34.1")
93-
self.assertEqual(self.version_comparator.extract_os_version_nums("34.13.4"), "34.13.4")
94-
self.assertEqual(self.version_comparator.extract_os_version_nums("34.13.4~18.04.1"), "34.13.4")
95-
self.assertEqual(self.version_comparator.extract_os_version_nums("34.13.4-ab+18.04.1"), "34.13.4")
96-
self.assertEqual(self.version_comparator.extract_os_version_nums("34.13.4abc-18.04.1"), "34.13.4")
97-
self.assertEqual(self.version_comparator.extract_os_version_nums("abc.34.13.4!@abc"), "34.13.4")
29+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34"), "34")
30+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34~18"), "34")
31+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34.~18.04"), "34")
32+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34.a+18.04.1"), "34")
33+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34abc-18.04"), "34")
34+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("abc34~18.04"), "34")
35+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("abc34~18.04.123"), "34")
36+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34~25.1.2-18.04.1"), "34")
37+
38+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34.1~18.04.1"), "34.1")
39+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34.13.4"), "34.13.4")
40+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34.13.4~18.04.1"), "34.13.4")
41+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34.13.4-ab+18.04.1"), "34.13.4")
42+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("34.13.4abc-18.04.1"), "34.13.4")
43+
self.assertEqual(self.version_comparator.extract_version_from_os_version_nums("abc.34.13.4!@abc"), "34.13.4")
9844

9945
def test_linux_os_version_comparison(self):
10046
""" Test compare versions logic Ubuntuproclient version with existing vm version """
101-
test_extracted_good_version = self.version_comparator.extract_os_version_nums("34.13.4~18.04.1") # return 34
102-
103-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_good_version, "34.13.4"), 0) # equal 34.13.4 == 34.13.4
104-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_good_version, "34.13.3"), 1) # greater 34.13.4 > 34.13.3
105-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_good_version, "34.13.5"), -1) # less 34.13.4 < 34.13.5
106-
107-
test_extracted_bad_version = self.version_comparator.extract_os_version_nums("abc~18.04.1") # return ""
108-
self.assertEqual(self.version_comparator.compare_version_nums(test_extracted_bad_version, "34.13.4"), -1) # less "" < 34.13.4
109-
110-
def test_os_version_sort_comparator(self):
111-
""" Test sorting comparator on linux os version """
112-
unsorted_os_versions = [
113-
"32.101.~18.01",
114-
"32.101.15~18",
115-
"abc34~18.04",
116-
"32~18.04.01",
117-
"32.1~18.04.01"
118-
]
47+
test_extracted_good_version = self.version_comparator.extract_version_from_os_version_nums("34.13.4~18.04.1") # return 34
11948

120-
expected_sorted_os_versions = [
121-
"abc34~18.04",
122-
"32.101.15~18",
123-
"32.101.~18.01",
124-
"32.1~18.04.01",
125-
"32~18.04.01"
126-
]
49+
self.assertEqual(self.version_comparator.compare_versions(test_extracted_good_version, "34.13.4"), 0) # equal 34.13.4 == 34.13.4
50+
self.assertEqual(self.version_comparator.compare_versions(test_extracted_good_version, "34.13.3"), 1) # greater 34.13.4 > 34.13.3
51+
self.assertEqual(self.version_comparator.compare_versions(test_extracted_good_version, "34.13.5"), -1) # less 34.13.4 < 34.13.5
12752

128-
self.assertEqual(self.version_comparator.sort_versions_desc_order(unsorted_os_versions), expected_sorted_os_versions)
53+
test_extracted_bad_version = self.version_comparator.extract_version_from_os_version_nums("abc~18.04.1") # return ""
54+
self.assertEqual(self.version_comparator.compare_versions(test_extracted_bad_version, "34.13.4"), -1) # less "" < 34.13.4
12955

13056

13157
if __name__ == '__main__':

src/extension/src/ActionHandler.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
from extension.src.Constants import Constants
2424
from extension.src.EnableCommandHandler import EnableCommandHandler
2525
from extension.src.InstallCommandHandler import InstallCommandHandler
26-
from extension.src.Utility import Utility
27-
from extension.src.VersionComparatorHandler import VersionComparatorHandler
26+
from extension.src.ExtVersionComparator import ExtVersionComparator
2827
from extension.src.local_loggers.StdOutFileMirror import StdOutFileMirror
2928

3029

@@ -49,7 +48,7 @@ def __init__(self, logger, env_layer, telemetry_writer, utility, runtime_context
4948
self.file_logger = None
5049
self.operation_id_substitute_for_all_actions_in_telemetry = str((datetime.datetime.utcnow()).strftime(Constants.UTC_DATETIME_FORMAT))
5150
self.seq_no = self.ext_config_settings_handler.get_seq_no_from_env_var()
52-
self.version_comparator_handler = VersionComparatorHandler()
51+
self.ext_version_comparator = ExtVersionComparator()
5352

5453
def determine_operation(self, command):
5554
switcher = {
@@ -228,7 +227,7 @@ def update(self):
228227
self.logger.log("Fetching the extension version preceding current from all available versions...")
229228

230229
# use custom sort logic to sort path based on version numbers
231-
sorted_versions = self.version_comparator_handler.sort_versions_desc_order(paths_to_all_versions)
230+
sorted_versions = self.ext_version_comparator.sort_ext_paths_desc_order(paths_to_all_versions)
232231
self.logger.log_debug("List of extension versions in descending order: [SortedVersion={0}]".format(sorted_versions))
233232

234233
preceding_version_path = sorted_versions[1]

0 commit comments

Comments
 (0)