Merge lp:~rvb/maas/multifield-power_parameters into lp:~maas-committers/maas/trunk

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 613
Proposed branch: lp:~rvb/maas/multifield-power_parameters
Merge into: lp:~maas-committers/maas/trunk
Prerequisite: lp:~rvb/maas/multifield
Diff against target: 243 lines (+47/-148)
2 files modified
src/maasserver/power_parameters.py (+34/-94)
src/maasserver/tests/test_power_parameters.py (+13/-54)
To merge this branch: bzr merge lp:~rvb/maas/multifield-power_parameters
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Review via email: mp+108191@code.launchpad.net

Commit message

Update power_parameter module to use DictCharField.

Description of the change

This branch simply updates src/maasserver/power_parameter.py to use DictCharField instead of a ad hoc structure. Note that this simplifies the code and the tests because all the validation will be done using DictCharField's validation features (which in turns leverages the stock validation functionality present in Django).

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Nice!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/power_parameters.py'
2--- src/maasserver/power_parameters.py 2012-05-25 16:13:50 +0000
3+++ src/maasserver/power_parameters.py 2012-06-05 11:01:20 +0000
4@@ -14,7 +14,7 @@
5 power type with a set of power parameters.
6
7 To define a new set of power parameters for a new power_type: create a new
8-mapping between the new power type and a list of PowerParameter instances in
9+mapping between the new power type and a DictCharField instance in
10 `POWER_TYPE_PARAMETERS`.
11 """
12
13@@ -27,108 +27,48 @@
14 __metaclass__ = type
15 __all__ = [
16 'POWER_TYPE_PARAMETERS',
17- 'validate_power_parameters',
18 ]
19
20-from collections import namedtuple
21-from operator import attrgetter
22
23-from django.core.exceptions import ValidationError
24+from django import forms
25+from maasserver.config_forms import DictCharField
26 from provisioningserver.enum import POWER_TYPE
27
28
29-PowerParameter = namedtuple(
30- 'PowerParameter',
31- [
32- # 'display' will be used in the UI as the title of the field.
33- 'display',
34- # 'name' is the actual name of this parameter as used in the JSON
35- # structure (power parameters are stored as JSON dicts).
36- 'name',
37- ])
38-
39-
40 POWER_TYPE_PARAMETERS = {
41 POWER_TYPE.WAKE_ON_LAN:
42- [
43- PowerParameter(
44- display='Address',
45- name='power_address',
46- ),
47- ],
48+ DictCharField(
49+ [
50+ ('power_address', forms.CharField(label="Address")),
51+ ],
52+ required=False,
53+ skip_check=True),
54 POWER_TYPE.VIRSH:
55- [
56- PowerParameter(
57- display='Driver',
58- name='driver',
59- ),
60- PowerParameter(
61- display='Username',
62- name='username',
63- ),
64- PowerParameter(
65- display='Address',
66- name='power_address',
67- ),
68- PowerParameter(
69- display='power_id',
70- name='power_id',
71- ),
72- ],
73+ DictCharField(
74+ [
75+ ('driver', forms.CharField(label="Driver")),
76+ ('username', forms.CharField(label="Username")),
77+ ('power_address', forms.CharField(label="Address")),
78+ ('power_id', forms.CharField(label="Power ID")),
79+ ],
80+ required=False,
81+ skip_check=True),
82 POWER_TYPE.IPMI:
83- [
84- PowerParameter(
85- display='Address',
86- name='power_address',
87- ),
88- PowerParameter(
89- display='User',
90- name='power_user',
91- ),
92- PowerParameter(
93- display='Password',
94- name='power_pass',
95- ),
96- ],
97+ DictCharField(
98+ [
99+ ('power_address', forms.CharField(label="Address")),
100+ ('power_user', forms.CharField(label="User")),
101+ ('power_pass', forms.CharField(label="Password")),
102+ ],
103+ required=False,
104+ skip_check=True),
105 POWER_TYPE.IPMI_LAN:
106- [
107- PowerParameter(
108- display='User',
109- name='power_user',
110- ),
111- PowerParameter(
112- display='Password',
113- name='power_pass',
114- ),
115- PowerParameter(
116- display='power_id',
117- name='power_id',
118- ),
119- ]
120+ DictCharField(
121+ [
122+ ('power_user', forms.CharField(label="User")),
123+ ('power_pass', forms.CharField(label="Password")),
124+ ('power_id', forms.CharField(label="Power ID")),
125+ ],
126+ required=False,
127+ skip_check=True),
128 }
129-
130-
131-def validate_power_parameters(power_parameters, power_type):
132- """Validate that the given power parameters:
133- - the given power_parameter argument must be a dictionary.
134- - the keys of the given power_parameter argument must be a subset of
135- the possible parameters for this power type.
136- If one of these assertions is not true, raise a ValidationError.
137- """
138- if not isinstance(power_parameters, dict):
139- raise ValidationError(
140- "The given power parameters should be a dictionary.")
141- # Fetch the expected power_parameter related to the power_type. If the
142- # power_type is unknown, don't validate power_parameter. We don't want
143- # to block things if one wants to use a custom power_type.
144- expected_power_parameters = map(attrgetter(
145- 'name'), POWER_TYPE_PARAMETERS.get(power_type, []))
146- if len(expected_power_parameters) != 0:
147- unknown_fields = set(
148- power_parameters).difference(expected_power_parameters)
149- if len(unknown_fields) != 0:
150- raise ValidationError(
151- "These field(s) are invalid for this power type: %s. "
152- "Allowed fields: %s." % (
153- ', '.join(unknown_fields),
154- ', '.join(expected_power_parameters)))
155
156=== modified file 'src/maasserver/tests/test_power_parameters.py'
157--- src/maasserver/tests/test_power_parameters.py 2012-05-25 16:13:50 +0000
158+++ src/maasserver/tests/test_power_parameters.py 2012-06-05 11:01:20 +0000
159@@ -12,22 +12,17 @@
160 __metaclass__ = type
161 __all__ = []
162
163-from operator import attrgetter
164-
165-from django.core.exceptions import ValidationError
166-from maasserver.power_parameters import (
167- POWER_TYPE_PARAMETERS,
168- PowerParameter,
169- validate_power_parameters,
170- )
171-from maasserver.testing.factory import factory
172+from maasserver.config_forms import DictCharField
173+from maasserver.power_parameters import POWER_TYPE_PARAMETERS
174 from maasserver.testing.testcase import TestCase
175 from maasserver.utils import map_enum
176 from maastesting.matchers import ContainsAll
177 from provisioningserver.enum import POWER_TYPE
178 from testtools.matchers import (
179 AllMatch,
180+ Equals,
181 IsInstance,
182+ MatchesStructure,
183 )
184
185
186@@ -38,48 +33,12 @@
187 self.assertIsInstance(POWER_TYPE_PARAMETERS, dict)
188 self.assertThat(power_types, ContainsAll(POWER_TYPE_PARAMETERS))
189
190- def test_POWER_TYPE_PARAMETERS_values_are_PowerParameter(self):
191- params = sum(POWER_TYPE_PARAMETERS.values(), [])
192- self.assertThat(params, AllMatch(IsInstance(PowerParameter)))
193-
194-
195-class TestPowerParameterHelpers(TestCase):
196-
197- def test_validate_power_parameters_requires_dict(self):
198- exception = self.assertRaises(
199- ValidationError, validate_power_parameters,
200- factory.getRandomString(), factory.getRandomString())
201- self.assertEqual(
202- ["The given power parameters should be a dictionary."],
203- exception.messages)
204-
205- def test_validate_power_parameters_rejects_unknown_field(self):
206- # If power_type is a known power type, the fields in the provided
207- # power_parameters dict are checked.
208- power_parameters = {"invalid-power-type": factory.getRandomString()}
209- power_type = POWER_TYPE.WAKE_ON_LAN
210- expected_power_parameters = map(attrgetter(
211- 'name'), POWER_TYPE_PARAMETERS.get(power_type, []))
212- exception = self.assertRaises(
213- ValidationError, validate_power_parameters,
214- power_parameters, power_type)
215- expected_message = (
216- "These field(s) are invalid for this power type: "
217- "invalid-power-type. Allowed fields: %s." % ', '.join(
218- expected_power_parameters))
219- self.assertEqual([expected_message], exception.messages)
220-
221- def test_validate_power_parameters_validates_if_unknown_power_type(self):
222- # If power_type is not a known power type, no check of the fields in
223- # power_parameter is performed.
224- power_parameters = {
225- factory.getRandomString(): factory.getRandomString()}
226- power_type = factory.getRandomString()
227- self.assertIsNone(
228- validate_power_parameters(power_parameters, power_type))
229-
230- def test_validate_power_parameters_validates_with_power_type_info(self):
231- power_parameters = {'power_address': factory.getRandomString()}
232- power_type = POWER_TYPE.WAKE_ON_LAN
233- self.assertIsNone(
234- validate_power_parameters(power_parameters, power_type))
235+ def test_POWER_TYPE_PARAMETERS_values_are_DictCharField(self):
236+ self.assertThat(
237+ POWER_TYPE_PARAMETERS.values(),
238+ AllMatch(IsInstance(DictCharField)))
239+
240+ def test_POWER_TYPE_PARAMETERS_DictCharField_objects_have_skip_check(self):
241+ self.assertThat(
242+ POWER_TYPE_PARAMETERS.values(),
243+ AllMatch(MatchesStructure(skip_check=Equals(True))))