Merge ~ltrager/maas:script_result_skip into maas:master
- Git
- lp:~ltrager/maas
- script_result_skip
- Merge into master
Proposed by
Lee Trager
Status: | Merged |
---|---|
Approved by: | Andres Rodriguez |
Approved revision: | f7b546b38aee71d52902b23f60f4910c28ce53aa |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~ltrager/maas:script_result_skip |
Merge into: | maas:master |
Diff against target: |
295 lines (+74/-17) 10 files modified
src/maasserver/static/js/angular/directives/script_status.js (+5/-1) src/maasserver/static/js/angular/directives/tests/test_script_status.js (+6/-0) src/maasserver/static/partials/script-results-list.html (+4/-4) src/metadataserver/builtin_scripts/smartctl.py (+7/-0) src/metadataserver/builtin_scripts/tests/test_smartctl.py (+10/-1) src/metadataserver/enum.py (+3/-1) src/metadataserver/migrations/builtin/0018_script_result_skipped.py (+23/-0) src/metadataserver/models/scriptresult.py (+7/-4) src/metadataserver/models/scriptset.py (+2/-0) src/metadataserver/models/tests/test_scriptresult.py (+7/-6) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
MAAS Lander | Approve | ||
Review via email: mp+343139@code.launchpad.net |
Commit message
LP: #1760919 - Allow ScriptResults to be skipped
Scripts may now signal 'skipped' in the result YAML. This tells MAAS the
script was unable to run but does not change the state of the node. The SMART
tests use 'skipped' when SMART is unavailable on a device.
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/src/maasserver/static/js/angular/directives/script_status.js b/src/maasserver/static/js/angular/directives/script_status.js | |||
2 | index 10d6316..fd8e793 100644 | |||
3 | --- a/src/maasserver/static/js/angular/directives/script_status.js | |||
4 | +++ b/src/maasserver/static/js/angular/directives/script_status.js | |||
5 | @@ -1,4 +1,4 @@ | |||
7 | 1 | /* Copyright 2017 Canonical Ltd. This software is licensed under the | 1 | /* Copyright 2017-2018 Canonical Ltd. This software is licensed under the |
8 | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). |
9 | 3 | * | 3 | * |
10 | 4 | * Script status icon select directive. | 4 | * Script status icon select directive. |
11 | @@ -51,6 +51,10 @@ angular.module('MAAS').directive('maasScriptStatus', function() { | |||
12 | 51 | case 4: | 51 | case 4: |
13 | 52 | $scope.icon = 'p-icon--timed-out'; | 52 | $scope.icon = 'p-icon--timed-out'; |
14 | 53 | break; | 53 | break; |
15 | 54 | // SCRIPT_STATUS.SKIPPED | ||
16 | 55 | case 9: | ||
17 | 56 | $scope.icon = 'p-icon--warning'; | ||
18 | 57 | break; | ||
19 | 54 | case -1: | 58 | case -1: |
20 | 55 | // No scripts have been run. | 59 | // No scripts have been run. |
21 | 56 | $scope.show = false; | 60 | $scope.show = false; |
22 | diff --git a/src/maasserver/static/js/angular/directives/tests/test_script_status.js b/src/maasserver/static/js/angular/directives/tests/test_script_status.js | |||
23 | index c43d192..d51b0d4 100644 | |||
24 | --- a/src/maasserver/static/js/angular/directives/tests/test_script_status.js | |||
25 | +++ b/src/maasserver/static/js/angular/directives/tests/test_script_status.js | |||
26 | @@ -87,6 +87,12 @@ describe("maasScriptStatus", function() { | |||
27 | 87 | expect(select.attr("class")).toBe("p-icon--timed-out"); | 87 | expect(select.attr("class")).toBe("p-icon--timed-out"); |
28 | 88 | }); | 88 | }); |
29 | 89 | 89 | ||
30 | 90 | it("SCRIPT_STATUS.SKIPPED", function() { | ||
31 | 91 | var directive = compileDirective("9"); | ||
32 | 92 | var select = directive.find("span"); | ||
33 | 93 | expect(select.attr("class")).toBe("p-icon--warning"); | ||
34 | 94 | }); | ||
35 | 95 | |||
36 | 90 | it("NONE", function() { | 96 | it("NONE", function() { |
37 | 91 | var directive = compileDirective("-1"); | 97 | var directive = compileDirective("-1"); |
38 | 92 | var select = directive.find("span"); | 98 | var select = directive.find("span"); |
39 | diff --git a/src/maasserver/static/partials/script-results-list.html b/src/maasserver/static/partials/script-results-list.html | |||
40 | index 1c1fa4c..187a8cb 100644 | |||
41 | --- a/src/maasserver/static/partials/script-results-list.html | |||
42 | +++ b/src/maasserver/static/partials/script-results-list.html | |||
43 | @@ -32,8 +32,8 @@ | |||
44 | 32 | <td class="col-3" aria-label="Date"><span data-ng-hide="result.showing_history">{$ result.updated $}</span></td> | 32 | <td class="col-3" aria-label="Date"><span data-ng-hide="result.showing_history">{$ result.updated $}</span></td> |
45 | 33 | <td class="col-2" aria-label="Result"> | 33 | <td class="col-2" aria-label="Result"> |
46 | 34 | <span data-ng-hide="result.showing_history"> | 34 | <span data-ng-hide="result.showing_history"> |
49 | 35 | <!-- Only link to the testing result when we've received it. This is indicated with status 2(passed), 3(failed), 4(timedout), 6(degraded), 8(failed installing)--> | 35 | <!-- Only link to the testing result when we've received it. This is indicated with status 2(passed), 3(failed), 4(timedout), 6(degraded), 8(failed installing), 9(skipped)--> |
50 | 36 | {$ result.status_name $} <a data-ng-if="result.status === 2 || result.status === 3 || result.status === 4 || result.status === 6 || result.status === 8" href="#/{$ type_name $}/{$ node.system_id $}/{$ section.area $}/{$ result.id $}">View log</a> | 36 | {$ result.status_name $} <a data-ng-if="result.status === 2 || result.status === 3 || result.status === 4 || result.status === 6 || result.status === 8 || result.status === 9" href="#/{$ type_name $}/{$ node.system_id $}/{$ section.area $}/{$ result.id $}">View log</a> |
51 | 37 | </span> | 37 | </span> |
52 | 38 | </td> | 38 | </td> |
53 | 39 | <td class="col-1"> | 39 | <td class="col-1"> |
54 | @@ -84,8 +84,8 @@ | |||
55 | 84 | <td class="col-1" aria-label="Runtime"><span data-maas-script-run-time="script-runtime" data-start-time="item.starttime" data-run-time="{{item.runtime}}" data-estimated-run-time="{{item.estimated_runtime}}" data-script-status="item.status"></span></td> | 84 | <td class="col-1" aria-label="Runtime"><span data-maas-script-run-time="script-runtime" data-start-time="item.starttime" data-run-time="{{item.runtime}}" data-estimated-run-time="{{item.estimated_runtime}}" data-script-status="item.status"></span></td> |
56 | 85 | <td class="col-3" aria-label="Date">{$ item.updated $}</td> | 85 | <td class="col-3" aria-label="Date">{$ item.updated $}</td> |
57 | 86 | <td class="col-2" aria-label="Status"> | 86 | <td class="col-2" aria-label="Status"> |
60 | 87 | <!-- Only link to the testing result when we've received it. This is indicated with status 2(passed), 3(failed), 4(timedout), 6(degraded), 8(failed installing)--> | 87 | <!-- Only link to the testing result when we've received it. This is indicated with status 2(passed), 3(failed), 4(timedout), 6(degraded), 8(failed installing), 9(skipped)--> |
61 | 88 | {$ item.status_name $} <a data-ng-if="item.status === 2 || item.status === 3 || item.status === 4 || item.status === 6 || item.status === 8" href="#/{$ type_name $}/{$ node.system_id $}/{$ section.area $}/{$ item.id $}">View log</a> | 88 | {$ item.status_name $} <a data-ng-if="item.status === 2 || item.status === 3 || item.status === 4 || item.status === 6 || item.status === 8 || item.status === 9" href="#/{$ type_name $}/{$ node.system_id $}/{$ section.area $}/{$ item.id $}">View log</a> |
62 | 89 | </td> | 89 | </td> |
63 | 90 | </tr> | 90 | </tr> |
64 | 91 | </tbody> | 91 | </tbody> |
65 | diff --git a/src/metadataserver/builtin_scripts/smartctl.py b/src/metadataserver/builtin_scripts/smartctl.py | |||
66 | index 5cff6d8..6b747f7 100644 | |||
67 | --- a/src/metadataserver/builtin_scripts/smartctl.py | |||
68 | +++ b/src/metadataserver/builtin_scripts/smartctl.py | |||
69 | @@ -35,6 +35,7 @@ | |||
70 | 35 | # --- End MAAS 1.0 script metadata --- | 35 | # --- End MAAS 1.0 script metadata --- |
71 | 36 | 36 | ||
72 | 37 | import argparse | 37 | import argparse |
73 | 38 | import os | ||
74 | 38 | import re | 39 | import re |
75 | 39 | from subprocess import ( | 40 | from subprocess import ( |
76 | 40 | CalledProcessError, | 41 | CalledProcessError, |
77 | @@ -49,6 +50,8 @@ from subprocess import ( | |||
78 | 49 | import sys | 50 | import sys |
79 | 50 | from time import sleep | 51 | from time import sleep |
80 | 51 | 52 | ||
81 | 53 | import yaml | ||
82 | 54 | |||
83 | 52 | # We're just reading the SMART data or asking the drive to run a self test. | 55 | # We're just reading the SMART data or asking the drive to run a self test. |
84 | 53 | # If this takes more then a minute there is something wrong the with drive. | 56 | # If this takes more then a minute there is something wrong the with drive. |
85 | 54 | TIMEOUT = 60 | 57 | TIMEOUT = 60 |
86 | @@ -84,6 +87,10 @@ def check_SMART_support(storage): | |||
87 | 84 | print( | 87 | print( |
88 | 85 | 'INFO: Unable to run test. The following drive ' | 88 | 'INFO: Unable to run test. The following drive ' |
89 | 86 | 'does not support SMART: %s\n' % storage) | 89 | 'does not support SMART: %s\n' % storage) |
90 | 90 | result_path = os.environ.get('RESULT_PATH') | ||
91 | 91 | if result_path is not None: | ||
92 | 92 | with open(result_path, 'w') as results_file: | ||
93 | 93 | yaml.safe_dump({'status': 'skipped'}, results_file) | ||
94 | 87 | sys.exit() | 94 | sys.exit() |
95 | 88 | print('INFO: SMART support is available; continuing...') | 95 | print('INFO: SMART support is available; continuing...') |
96 | 89 | 96 | ||
97 | diff --git a/src/metadataserver/builtin_scripts/tests/test_smartctl.py b/src/metadataserver/builtin_scripts/tests/test_smartctl.py | |||
98 | index 9781549..11767a3 100644 | |||
99 | --- a/src/metadataserver/builtin_scripts/tests/test_smartctl.py | |||
100 | +++ b/src/metadataserver/builtin_scripts/tests/test_smartctl.py | |||
101 | @@ -1,10 +1,11 @@ | |||
103 | 1 | # Copyright 2017 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2017-2018 Canonical Ltd. This software is licensed under the |
104 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
105 | 3 | 3 | ||
106 | 4 | """Test smartctl functions.""" | 4 | """Test smartctl functions.""" |
107 | 5 | 5 | ||
108 | 6 | __all__ = [] | 6 | __all__ = [] |
109 | 7 | 7 | ||
110 | 8 | import io | ||
111 | 8 | from subprocess import ( | 9 | from subprocess import ( |
112 | 9 | CalledProcessError, | 10 | CalledProcessError, |
113 | 10 | DEVNULL, | 11 | DEVNULL, |
114 | @@ -81,6 +82,11 @@ class TestSmartCTL(MAASTestCase): | |||
115 | 81 | mock_check_output = self.patch(smartctl, "check_output") | 82 | mock_check_output = self.patch(smartctl, "check_output") |
116 | 82 | mock_check_output.return_value = b"SMART support is not available." | 83 | mock_check_output.return_value = b"SMART support is not available." |
117 | 83 | mock_print = self.patch(smartctl, "print") | 84 | mock_print = self.patch(smartctl, "print") |
118 | 85 | result_path = factory.make_name("result_path") | ||
119 | 86 | self.patch(smartctl.os, "environ", {"RESULT_PATH": result_path}) | ||
120 | 87 | mock_open = self.patch(smartctl, "open") | ||
121 | 88 | mock_open.return_value = io.StringIO() | ||
122 | 89 | mock_yaml_safe_dump = self.patch(smartctl.yaml, "safe_dump") | ||
123 | 84 | 90 | ||
124 | 85 | self.assertRaises(SystemExit, smartctl.check_SMART_support, storage) | 91 | self.assertRaises(SystemExit, smartctl.check_SMART_support, storage) |
125 | 86 | self.assertThat(mock_check_output, MockCalledOnceWith( | 92 | self.assertThat(mock_check_output, MockCalledOnceWith( |
126 | @@ -95,6 +101,9 @@ class TestSmartCTL(MAASTestCase): | |||
127 | 95 | 'sudo -n smartctl --all %s\n' % storage), | 101 | 'sudo -n smartctl --all %s\n' % storage), |
128 | 96 | call('INFO: Unable to run test. The following drive does ' | 102 | call('INFO: Unable to run test. The following drive does ' |
129 | 97 | 'not support SMART: %s\n' % storage))) | 103 | 'not support SMART: %s\n' % storage))) |
130 | 104 | self.assertThat(mock_open, MockCalledOnceWith(result_path, "w")) | ||
131 | 105 | self.assertThat(mock_yaml_safe_dump, MockCalledOnceWith( | ||
132 | 106 | {'status': 'skipped'}, mock_open.return_value)) | ||
133 | 98 | 107 | ||
134 | 99 | def test_run_smartctl_selftest(self): | 108 | def test_run_smartctl_selftest(self): |
135 | 100 | storage = factory.make_name('storage') | 109 | storage = factory.make_name('storage') |
136 | diff --git a/src/metadataserver/enum.py b/src/metadataserver/enum.py | |||
137 | index 7188914..d9a362c 100644 | |||
138 | --- a/src/metadataserver/enum.py | |||
139 | +++ b/src/metadataserver/enum.py | |||
140 | @@ -76,6 +76,7 @@ class SCRIPT_STATUS: | |||
141 | 76 | DEGRADED = 6 | 76 | DEGRADED = 6 |
142 | 77 | INSTALLING = 7 | 77 | INSTALLING = 7 |
143 | 78 | FAILED_INSTALLING = 8 | 78 | FAILED_INSTALLING = 8 |
144 | 79 | SKIPPED = 9 | ||
145 | 79 | 80 | ||
146 | 80 | 81 | ||
147 | 81 | SCRIPT_STATUS_CHOICES = ( | 82 | SCRIPT_STATUS_CHOICES = ( |
148 | @@ -87,7 +88,8 @@ SCRIPT_STATUS_CHOICES = ( | |||
149 | 87 | (SCRIPT_STATUS.ABORTED, "Aborted"), | 88 | (SCRIPT_STATUS.ABORTED, "Aborted"), |
150 | 88 | (SCRIPT_STATUS.DEGRADED, "Degraded"), | 89 | (SCRIPT_STATUS.DEGRADED, "Degraded"), |
151 | 89 | (SCRIPT_STATUS.INSTALLING, "Installing dependencies"), | 90 | (SCRIPT_STATUS.INSTALLING, "Installing dependencies"), |
153 | 90 | (SCRIPT_STATUS.FAILED_INSTALLING, "Failed installing dependencies") | 91 | (SCRIPT_STATUS.FAILED_INSTALLING, "Failed installing dependencies"), |
154 | 92 | (SCRIPT_STATUS.SKIPPED, "Skipped"), | ||
155 | 91 | ) | 93 | ) |
156 | 92 | 94 | ||
157 | 93 | 95 | ||
158 | diff --git a/src/metadataserver/migrations/builtin/0018_script_result_skipped.py b/src/metadataserver/migrations/builtin/0018_script_result_skipped.py | |||
159 | 94 | new file mode 100644 | 96 | new file mode 100644 |
160 | index 0000000..0e3eca6 | |||
161 | --- /dev/null | |||
162 | +++ b/src/metadataserver/migrations/builtin/0018_script_result_skipped.py | |||
163 | @@ -0,0 +1,23 @@ | |||
164 | 1 | # -*- coding: utf-8 -*- | ||
165 | 2 | # Generated by Django 1.11.11 on 2018-04-12 20:44 | ||
166 | 3 | from __future__ import unicode_literals | ||
167 | 4 | |||
168 | 5 | from django.db import ( | ||
169 | 6 | migrations, | ||
170 | 7 | models, | ||
171 | 8 | ) | ||
172 | 9 | |||
173 | 10 | |||
174 | 11 | class Migration(migrations.Migration): | ||
175 | 12 | |||
176 | 13 | dependencies = [ | ||
177 | 14 | ('metadataserver', '0017_store_requested_scripts'), | ||
178 | 15 | ] | ||
179 | 16 | |||
180 | 17 | operations = [ | ||
181 | 18 | migrations.AlterField( | ||
182 | 19 | model_name='scriptresult', | ||
183 | 20 | name='status', | ||
184 | 21 | field=models.IntegerField(choices=[(0, 'Pending'), (1, 'Running'), (2, 'Passed'), (3, 'Failed'), (4, 'Timed out'), (5, 'Aborted'), (6, 'Degraded'), (7, 'Installing dependencies'), (8, 'Failed installing dependencies'), (9, 'Skipped')], default=0), | ||
185 | 22 | ), | ||
186 | 23 | ] | ||
187 | diff --git a/src/metadataserver/models/scriptresult.py b/src/metadataserver/models/scriptresult.py | |||
188 | index 9cd657f..add7c94 100644 | |||
189 | --- a/src/metadataserver/models/scriptresult.py | |||
190 | +++ b/src/metadataserver/models/scriptresult.py | |||
191 | @@ -189,10 +189,10 @@ class ScriptResult(CleanSave, TimestampedModel): | |||
192 | 189 | raise ValidationError('YAML must be a dictionary.') | 189 | raise ValidationError('YAML must be a dictionary.') |
193 | 190 | 190 | ||
194 | 191 | if parsed_yaml.get('status') not in [ | 191 | if parsed_yaml.get('status') not in [ |
196 | 192 | 'passed', 'failed', 'degraded', 'timedout', None]: | 192 | 'passed', 'failed', 'degraded', 'timedout', 'skipped', None]: |
197 | 193 | raise ValidationError( | 193 | raise ValidationError( |
200 | 194 | 'status must be "passed", "failed", "degraded", or ' | 194 | 'status must be "passed", "failed", "degraded", ' |
201 | 195 | '"timedout".') | 195 | '"timedout", or "skipped".') |
202 | 196 | 196 | ||
203 | 197 | results = parsed_yaml.get('results') | 197 | results = parsed_yaml.get('results') |
204 | 198 | if results is None: | 198 | if results is None: |
205 | @@ -274,6 +274,8 @@ class ScriptResult(CleanSave, TimestampedModel): | |||
206 | 274 | self.status = SCRIPT_STATUS.DEGRADED | 274 | self.status = SCRIPT_STATUS.DEGRADED |
207 | 275 | elif status == 'timedout': | 275 | elif status == 'timedout': |
208 | 276 | self.status = SCRIPT_STATUS.TIMEDOUT | 276 | self.status = SCRIPT_STATUS.TIMEDOUT |
209 | 277 | elif status == 'skipped': | ||
210 | 278 | self.status = SCRIPT_STATUS.SKIPPED | ||
211 | 277 | 279 | ||
212 | 278 | if self.script: | 280 | if self.script: |
213 | 279 | if script_version_id is not None: | 281 | if script_version_id is not None: |
214 | @@ -351,7 +353,8 @@ class ScriptResult(CleanSave, TimestampedModel): | |||
215 | 351 | elif self.ended is None and self.status in { | 353 | elif self.ended is None and self.status in { |
216 | 352 | SCRIPT_STATUS.PASSED, SCRIPT_STATUS.FAILED, | 354 | SCRIPT_STATUS.PASSED, SCRIPT_STATUS.FAILED, |
217 | 353 | SCRIPT_STATUS.TIMEDOUT, SCRIPT_STATUS.ABORTED, | 355 | SCRIPT_STATUS.TIMEDOUT, SCRIPT_STATUS.ABORTED, |
219 | 354 | SCRIPT_STATUS.DEGRADED, SCRIPT_STATUS.FAILED_INSTALLING}: | 356 | SCRIPT_STATUS.DEGRADED, SCRIPT_STATUS.FAILED_INSTALLING, |
220 | 357 | SCRIPT_STATUS.SKIPPED}: | ||
221 | 355 | self.ended = datetime.now() | 358 | self.ended = datetime.now() |
222 | 356 | if 'update_fields' in kwargs: | 359 | if 'update_fields' in kwargs: |
223 | 357 | kwargs['update_fields'].append('ended') | 360 | kwargs['update_fields'].append('ended') |
224 | diff --git a/src/metadataserver/models/scriptset.py b/src/metadataserver/models/scriptset.py | |||
225 | index 6836b57..f84399f 100644 | |||
226 | --- a/src/metadataserver/models/scriptset.py | |||
227 | +++ b/src/metadataserver/models/scriptset.py | |||
228 | @@ -68,6 +68,8 @@ def get_status_from_qs(qs): | |||
229 | 68 | if count == 0: | 68 | if count == 0: |
230 | 69 | return -1 | 69 | return -1 |
231 | 70 | # The status order below represents the order of precedence. | 70 | # The status order below represents the order of precedence. |
232 | 71 | # Skipped is omitted here otherwise one skipped test will show | ||
233 | 72 | # a warning icon in the UI on the test tab. | ||
234 | 71 | for status in ( | 73 | for status in ( |
235 | 72 | SCRIPT_STATUS.RUNNING, SCRIPT_STATUS.INSTALLING, | 74 | SCRIPT_STATUS.RUNNING, SCRIPT_STATUS.INSTALLING, |
236 | 73 | SCRIPT_STATUS.PENDING, SCRIPT_STATUS.ABORTED, | 75 | SCRIPT_STATUS.PENDING, SCRIPT_STATUS.ABORTED, |
237 | diff --git a/src/metadataserver/models/tests/test_scriptresult.py b/src/metadataserver/models/tests/test_scriptresult.py | |||
238 | index fedeb6d..ca72e72 100644 | |||
239 | --- a/src/metadataserver/models/tests/test_scriptresult.py | |||
240 | +++ b/src/metadataserver/models/tests/test_scriptresult.py | |||
241 | @@ -196,6 +196,7 @@ class TestScriptResult(MAASServerTestCase): | |||
242 | 196 | 'failed': SCRIPT_STATUS.FAILED, | 196 | 'failed': SCRIPT_STATUS.FAILED, |
243 | 197 | 'degraded': SCRIPT_STATUS.DEGRADED, | 197 | 'degraded': SCRIPT_STATUS.DEGRADED, |
244 | 198 | 'timedout': SCRIPT_STATUS.TIMEDOUT, | 198 | 'timedout': SCRIPT_STATUS.TIMEDOUT, |
245 | 199 | 'skipped': SCRIPT_STATUS.SKIPPED, | ||
246 | 199 | } | 200 | } |
247 | 200 | status = random.choice(list(status_choices.keys())) | 201 | status = random.choice(list(status_choices.keys())) |
248 | 201 | status_yaml = {'status': status} | 202 | status_yaml = {'status': status} |
249 | @@ -351,7 +352,7 @@ class TestScriptResult(MAASServerTestCase): | |||
250 | 351 | script_result.status = random.choice([ | 352 | script_result.status = random.choice([ |
251 | 352 | SCRIPT_STATUS.PASSED, SCRIPT_STATUS.FAILED, SCRIPT_STATUS.TIMEDOUT, | 353 | SCRIPT_STATUS.PASSED, SCRIPT_STATUS.FAILED, SCRIPT_STATUS.TIMEDOUT, |
252 | 353 | SCRIPT_STATUS.ABORTED, SCRIPT_STATUS.DEGRADED, | 354 | SCRIPT_STATUS.ABORTED, SCRIPT_STATUS.DEGRADED, |
254 | 354 | SCRIPT_STATUS.FAILED_INSTALLING]) | 355 | SCRIPT_STATUS.FAILED_INSTALLING, SCRIPT_STATUS.SKIPPED]) |
255 | 355 | script_result.save(update_fields=['status']) | 356 | script_result.save(update_fields=['status']) |
256 | 356 | self.assertIsNotNone(reload_object(script_result).ended) | 357 | self.assertIsNotNone(reload_object(script_result).ended) |
257 | 357 | 358 | ||
258 | @@ -362,7 +363,7 @@ class TestScriptResult(MAASServerTestCase): | |||
259 | 362 | script_result.status = random.choice([ | 363 | script_result.status = random.choice([ |
260 | 363 | SCRIPT_STATUS.PASSED, SCRIPT_STATUS.FAILED, SCRIPT_STATUS.TIMEDOUT, | 364 | SCRIPT_STATUS.PASSED, SCRIPT_STATUS.FAILED, SCRIPT_STATUS.TIMEDOUT, |
261 | 364 | SCRIPT_STATUS.ABORTED, SCRIPT_STATUS.DEGRADED, | 365 | SCRIPT_STATUS.ABORTED, SCRIPT_STATUS.DEGRADED, |
263 | 365 | SCRIPT_STATUS.FAILED_INSTALLING]) | 366 | SCRIPT_STATUS.FAILED_INSTALLING, SCRIPT_STATUS.SKIPPED]) |
264 | 366 | script_result.save(update_fields=['status']) | 367 | script_result.save(update_fields=['status']) |
265 | 367 | script_result = reload_object(script_result) | 368 | script_result = reload_object(script_result) |
266 | 368 | self.assertIsNotNone(script_result.started) | 369 | self.assertIsNotNone(script_result.started) |
267 | @@ -502,7 +503,7 @@ class TestScriptResult(MAASServerTestCase): | |||
268 | 502 | def test_read_results(self): | 503 | def test_read_results(self): |
269 | 503 | results = { | 504 | results = { |
270 | 504 | 'status': random.choice( | 505 | 'status': random.choice( |
272 | 505 | ['passed', 'failed', 'degraded', 'timedout']), | 506 | ['passed', 'failed', 'degraded', 'timedout', 'skipped']), |
273 | 506 | 'results': { | 507 | 'results': { |
274 | 507 | factory.make_name('key'): factory.make_name('value'), | 508 | factory.make_name('key'): factory.make_name('value'), |
275 | 508 | factory.make_name('key'): [ | 509 | factory.make_name('key'): [ |
276 | @@ -524,7 +525,7 @@ class TestScriptResult(MAASServerTestCase): | |||
277 | 524 | 525 | ||
278 | 525 | def test_read_results_does_not_require_results(self): | 526 | def test_read_results_does_not_require_results(self): |
279 | 526 | result = {'status': random.choice( | 527 | result = {'status': random.choice( |
281 | 527 | ['passed', 'failed', 'degraded', 'timedout'])} | 528 | ['passed', 'failed', 'degraded', 'timedout', 'skipped'])} |
282 | 528 | script_result = factory.make_ScriptResult( | 529 | script_result = factory.make_ScriptResult( |
283 | 529 | result=yaml.safe_dump(result).encode()) | 530 | result=yaml.safe_dump(result).encode()) |
284 | 530 | self.assertDictEqual(result, script_result.read_results()) | 531 | self.assertDictEqual(result, script_result.read_results()) |
285 | @@ -547,8 +548,8 @@ class TestScriptResult(MAASServerTestCase): | |||
286 | 547 | result=yaml.safe_dump(result).encode()) | 548 | result=yaml.safe_dump(result).encode()) |
287 | 548 | with self.assertRaisesRegex( | 549 | with self.assertRaisesRegex( |
288 | 549 | ValidationError, | 550 | ValidationError, |
291 | 550 | 'status must be "passed", "failed", "degraded", or ' | 551 | 'status must be "passed", "failed", "degraded", ' |
292 | 551 | '"timedout".'): | 552 | '"timedout", or "skipped".'): |
293 | 552 | script_result.read_results() | 553 | script_result.read_results() |
294 | 553 | 554 | ||
295 | 554 | def test_read_results_errors_when_dict_keys_not_str(self): | 555 | def test_read_results_errors_when_dict_keys_not_str(self): |
UNIT TESTS
-b script_result_skip lp:~ltrager/maas/+git/maas into -b master lp:~maas-committers/maas
STATUS: SUCCESS 52902b23f60f491 0c28ce53aa
COMMIT: f7b546b38aee71d