Merge ~d0ugal/maas:node-metadata-lp-1891027-2.7 into maas:2.7

Proposed by Dougal Matthews
Status: Merged
Approved by: Dougal Matthews
Approved revision: f96d25cf5efbaca02a0fcf5efb80ff167634b7a6
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~d0ugal/maas:node-metadata-lp-1891027-2.7
Merge into: maas:2.7
Diff against target: 125 lines (+35/-24)
2 files modified
src/metadataserver/models/scriptset.py (+12/-24)
src/metadataserver/models/tests/test_scriptset.py (+23/-0)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Adam Collard (community) Approve
Review via email: mp+389160@code.launchpad.net

Commit message

LP: #1891027 Use simpler nodemetadata matching

This simplifies the node metadata matching with a python comparisons and
removes the regular expression and pattern matching
support.

To post a comment you must log in.
Revision history for this message
Adam Collard (adam-collard) :
review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b node-metadata-lp-1891027-2.7 lp:~d0ugal/maas/+git/maas into -b 2.7 lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: f96d25cf5efbaca02a0fcf5efb80ff167634b7a6

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/metadataserver/models/scriptset.py b/src/metadataserver/models/scriptset.py
2index 1f1bf65..fb10603 100644
3--- a/src/metadataserver/models/scriptset.py
4+++ b/src/metadataserver/models/scriptset.py
5@@ -4,8 +4,6 @@
6 __all__ = ["ScriptSet", "get_status_from_qs", "translate_result_type"]
7
8 from datetime import timedelta
9-import fnmatch
10-import re
11
12 from django.contrib.postgres.fields import ArrayField
13 from django.core.exceptions import ObjectDoesNotExist, ValidationError
14@@ -229,26 +227,21 @@ class ScriptSetManager(Manager):
15 script_type=script_type,
16 )
17 modaliases = script_set.node.modaliases
18- regexes = []
19- for nmd in script_set.node.nodemetadata_set.filter(
20+ hw_pairs_qs = script_set.node.nodemetadata_set.filter(
21 Q(key__startswith="system_")
22 | Q(key__startswith="mainboard_")
23 | Q(key__startswith="firmware_")
24 | Q(key__startswith="chassis_")
25- ):
26- regexes.append("%s:%s" % (nmd.key, fnmatch.translate(nmd.value)))
27- if len(regexes) > 0:
28- node_hw_regex = re.compile("^%s$" % "|".join(regexes), re.I)
29- else:
30- node_hw_regex = None
31+ ).values_list("key", "value")
32+ hw_pairs = [":".join(t) for t in hw_pairs_qs]
33 for script in qs:
34 # If a script with the for_hardware field is selected by tag only
35 # add it if matching hardware is found.
36 if script.for_hardware:
37 found_hw_match = False
38- if node_hw_regex is not None:
39+ if hw_pairs:
40 for hardware in script.for_hardware:
41- if node_hw_regex.search(hardware) is not None:
42+ if hardware in hw_pairs:
43 found_hw_match = True
44 break
45 matches = filter_modaliases(modaliases, *script.ForHardware)
46@@ -469,18 +462,13 @@ class ScriptSet(CleanSave, Model):
47 if modaliases is None:
48 modaliases = self.node.modaliases
49
50- regexes = []
51- for nmd in self.node.nodemetadata_set.filter(
52+ hw_pairs_qs = self.node.nodemetadata_set.filter(
53 Q(key__startswith="system_")
54 | Q(key__startswith="mainboard_")
55 | Q(key__startswith="firmware_")
56 | Q(key__startswith="chassis_")
57- ):
58- regexes.append("%s:%s" % (nmd.key, fnmatch.translate(nmd.value)))
59- if len(regexes) > 0:
60- node_hw_regex = re.compile("^%s$" % "|".join(regexes), re.I)
61- else:
62- node_hw_regex = None
63+ ).values_list("key", "value")
64+ hw_pairs = [":".join(t) for t in hw_pairs_qs]
65
66 # Remove scripts autoselected at the start of commissioning but updated
67 # commissioning data shows the Script is no longer applicable.
68@@ -496,9 +484,9 @@ class ScriptSet(CleanSave, Model):
69 modaliases, *script_result.script.ForHardware
70 )
71 found_hw_match = False
72- if node_hw_regex is not None:
73+ if hw_pairs:
74 for hardware in script_result.script.for_hardware:
75- if node_hw_regex.search(hardware) is not None:
76+ if hardware in hw_pairs:
77 found_hw_match = True
78 break
79 matches = filter_modaliases(
80@@ -518,9 +506,9 @@ class ScriptSet(CleanSave, Model):
81 scripts = scripts.exclude(name__in=[s.name for s in self])
82 for script in scripts:
83 found_hw_match = False
84- if node_hw_regex is not None:
85+ if hw_pairs:
86 for hardware in script.for_hardware:
87- if node_hw_regex.search(hardware) is not None:
88+ if hardware in hw_pairs:
89 found_hw_match = True
90 break
91 matches = filter_modaliases(modaliases, *script.ForHardware)
92diff --git a/src/metadataserver/models/tests/test_scriptset.py b/src/metadataserver/models/tests/test_scriptset.py
93index d3597cb..5085090 100644
94--- a/src/metadataserver/models/tests/test_scriptset.py
95+++ b/src/metadataserver/models/tests/test_scriptset.py
96@@ -1201,6 +1201,29 @@ class TestScriptSet(MAASServerTestCase):
97 [script_result.name for script_result in script_set],
98 )
99
100+ def test_select_for_hardware_scripts_with_bracket_in_firmware(self):
101+ # Regression test for LP:1891213
102+ node = factory.make_Node()
103+ factory.make_NodeMetadata(
104+ node=node,
105+ key="mainboard_firmware_version",
106+ value="-[IVE156L-2.61]-",
107+ )
108+ script = factory.make_Script(
109+ script_type=SCRIPT_TYPE.COMMISSIONING,
110+ for_hardware=["mainboard_firmware_version:-[IVE156L-2.61]-"],
111+ )
112+ script_set = ScriptSet.objects.create_commissioning_script_set(
113+ node, [random.choice(script.tags)]
114+ )
115+
116+ script_set.select_for_hardware_scripts()
117+
118+ self.assertItemsEqual(
119+ list(NODE_INFO_SCRIPTS) + [script.name],
120+ [script_result.name for script_result in script_set],
121+ )
122+
123 def test_regenerate_storage(self):
124 node = factory.make_Node(interface=True)
125 script_set = factory.make_ScriptSet(node=node)

Subscribers

People subscribed via source and target branches