Skip to content

Commit b79b074

Browse files
committed
Upgrade more testcases to output messages
Signed-off-by: Matthias Büchse <matthias.buechse@alasca.cloud>
1 parent d4489c5 commit b79b074

4 files changed

Lines changed: 62 additions & 59 deletions

File tree

Tests/iaas/openstack_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,8 @@ def __init__(self):
232232
def __getattr__(self, key):
233233
val = self._values.get(key)
234234
if val is None:
235-
# this is too verbose
236-
# logger.debug(f'... {key}')
235+
# I thought this was too verbose, but it massively helps classifying log messages
236+
logger.debug(f'... {key}')
237237
try:
238238
ret = self._functions[key](self)
239239
except BaseException as e:

Tests/iaas/scs_0100_flavor_naming/flavor_names_check.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,19 @@ def compute_scs_flavors(flavors: typing.List[openstack.compute.v2.flavor.Flavor]
3838
return result
3939

4040

41+
def _log_errors(cause, names):
42+
"""helper to construct result for testcase"""
43+
if not names:
44+
return []
45+
message = f"{cause} with flavor(s): {', '.join(sorted(names))}"
46+
logger.error(message)
47+
return message
48+
49+
4150
def compute_scs_0100_syntax_check(scs_flavors: list) -> bool:
4251
"""This test ensures that each SCS flavor is indeed named correctly."""
4352
problems = [flv.name for flv, flavorname in scs_flavors if not flavorname]
44-
if problems:
45-
logger.error(f"scs-100-syntax-check: flavor(s) failed: {', '.join(sorted(problems))}")
46-
return not problems
53+
return _log_errors('syntax problems', problems)
4754

4855

4956
def compute_scs_0100_semantics_check(scs_flavors: list) -> bool:

Tests/iaas/scs_0102_image_metadata/image_metadata.py

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def is_outdated(img, now=time.time()):
100100

101101

102102
def _log_error(cause, offenders, channel=logging.ERROR):
103+
"""helper function to construct report messages"""
103104
if not offenders:
104105
return []
105106
names = [img.name for img in offenders]
@@ -111,36 +112,34 @@ def _log_error(cause, offenders, channel=logging.ERROR):
111112
def compute_scs_0102_prop_architecture(images, architectures=ARCHITECTURES):
112113
"""This test ensures that each image has a proper value for the property `architecture`."""
113114
offenders = [img for img in images if img.architecture not in architectures]
114-
_log_error('property architecture not correct', offenders)
115-
return not offenders
115+
return _log_error('property architecture not correct', offenders)
116116

117117

118118
# NOTE I think this is a recommendation
119119
def compute_scs_0102_prop_hash_algo(images):
120120
"""This test ensures that each image has a proper value for the property `hash_algo`."""
121121
offenders = [img for img in images if img.hash_algo not in ('sha256', 'sha512')]
122-
_log_error('property hash_algo invalid', offenders)
123-
return not offenders
122+
return _log_error('property hash_algo invalid', offenders)
124123

125124

126125
def compute_scs_0102_prop_min_disk(images):
127126
"""This test ensures that each image has a proper value for the property `min_disk`."""
128127
offenders1 = [img for img in images if not img.min_disk]
129-
_log_error('property min_disk not set', offenders1)
130128
offenders2 = [img for img in images if img.min_disk and img.min_disk * GIB < img.size]
131-
_log_error('property min_disk smaller than size', offenders2)
132-
return not offenders1 and not offenders2
129+
return (
130+
_log_error('property min_disk not set', offenders1) +
131+
_log_error('property min_disk smaller than size', offenders2)
132+
)
133133

134134

135135
def compute_scs_0102_prop_min_ram(images):
136136
"""This test ensures that each image has a proper value for the property `min_ram`."""
137-
offenders1 = [img for img in images if not img.min_ram]
138-
_log_error('property min_ram not set', offenders1)
139137
# emit a warning im RAM really low
140138
# NOTE this will probably only get noticed if an error occurs as well
141139
offenders2 = [img for img in images if img.min_ram and img.min_ram < 64]
142140
_log_error('property min_ram < 64 MiB', offenders2, channel=logging.WARNING)
143-
return not offenders1
141+
offenders1 = [img for img in images if not img.min_ram]
142+
return _log_error('property min_ram not set', offenders1)
144143

145144

146145
def compute_scs_0102_prop_os_version(images):
@@ -150,8 +149,7 @@ def compute_scs_0102_prop_os_version(images):
150149
# certain values for common operating systems.
151150
# - os_version not matching regexp r'[0-9\.]*' (should be a numeric version no)
152151
offenders = [img for img in images if not img.os_version]
153-
_log_error('property os_version not set', offenders)
154-
return not offenders
152+
return _log_error('property os_version not set', offenders)
155153

156154

157155
def compute_scs_0102_prop_os_distro(images):
@@ -160,8 +158,7 @@ def compute_scs_0102_prop_os_distro(images):
160158
# - os_distro not being all-lowercase (they all should be acc. to
161159
# https://docs.openstack.org/glance/2025.1/admin/useful-image-properties.html
162160
offenders = [img for img in images if not img.os_distro]
163-
_log_error('property os_distro not set', offenders)
164-
return not offenders
161+
return _log_error('property os_distro not set', offenders)
165162

166163

167164
def compute_scs_0102_prop_os_purpose(images, os_purposes=OS_PURPOSES):
@@ -173,41 +170,44 @@ def compute_scs_0102_prop_os_purpose(images, os_purposes=OS_PURPOSES):
173170
def compute_scs_0102_prop_hw_disk_bus(images, hw_disk_buses=HW_DISK_BUSES):
174171
"""This test ensures that each image has a proper value for the property `hw_disk_bus`."""
175172
offenders = [img for img in images if img.hw_disk_bus not in hw_disk_buses]
176-
_log_error('property hw_disk_bus not correct', offenders)
177-
return not offenders
173+
return _log_error('property hw_disk_bus not correct', offenders)
178174

179175

180176
def compute_scs_0102_prop_hypervisor_type(images, hypervisor_types=HYPERVISOR_TYPES):
181177
"""This test ensures that each image has a proper value for the property `hypervisor_type`."""
182178
offenders = [img for img in images if img.hypervisor_type not in hypervisor_types]
183-
_log_error('property hypervisor_type not correct', offenders)
184-
return not offenders
179+
return _log_error('property hypervisor_type not correct', offenders)
185180

186181

187182
def compute_scs_0102_prop_hw_rng_model(images, hw_rng_models=HW_RNG_MODELS):
188183
"""This test ensures that each image has a proper value for the property `hw_rng_model`."""
189184
offenders = [img for img in images if img.hw_rng_model not in hw_rng_models]
190-
_log_error('property hw_rng_model not correct', offenders)
191-
return not offenders
185+
return _log_error('property hw_rng_model not correct', offenders)
192186

193187

194188
def compute_scs_0102_prop_image_build_date(images, now=time.time()):
195189
"""This test ensures that each image has a proper value for the property `image_build_date`."""
196-
errors = 0
190+
offenders1 = []
191+
offenders2 = []
192+
offenders3 = []
197193
for img in images:
198194
rdate = parse_date(img.created_at, formats=STRICT_FORMATS)
199195
bdate_str = img.properties.get('image_build_date', '')
200196
bdate = parse_date(bdate_str)
201197
if not bdate:
202198
logger.error(f'Image "{img.name}": image_build_date "{bdate_str}" INVALID')
203-
errors += 1
199+
offenders1.append(img)
204200
elif bdate > rdate:
205201
logger.error(f'Image "{img.name}": image_build_date {bdate_str} AFTER registration date {img.created_at}')
206-
errors += 1
202+
offenders3.append(img)
207203
if (bdate or rdate) > now:
208204
logger.error(f'Image "{img.name}" has build time in the future: {bdate}')
209-
errors += 1
210-
return not errors
205+
offenders3.append(img)
206+
return (
207+
_log_error('image_build_date INVALID', offenders1, channel=logging.DEBUG) +
208+
_log_error('image_build_date AFTER registration date', offenders2, channel=logging.DEBUG) +
209+
_log_error('image build time in the future', offenders3, channel=logging.DEBUG)
210+
)
211211

212212

213213
# FIXME this is completely optional
@@ -218,8 +218,7 @@ def compute_scs_0102_prop_image_build_date(images, now=time.time()):
218218
def compute_scs_0102_prop_image_original_user(images):
219219
"""This test ensures that each image has a proper value for the property `image_original_user`."""
220220
offenders = [img for img in images if not img.properties.get('image_original_user')]
221-
_log_error('property image_original_user not set', offenders)
222-
return not offenders
221+
return _log_error('property image_original_user not set', offenders)
223222

224223

225224
def compute_scs_0102_prop_image_source(images):
@@ -230,34 +229,30 @@ def compute_scs_0102_prop_image_source(images):
230229
if img.properties.get('image_source') != 'private'
231230
if not is_url(img.properties.get('image_source', ''))
232231
]
233-
_log_error('property image_source INVALID (url or "private")', offenders)
234-
return not offenders
232+
return _log_error('property image_source INVALID (url or "private")', offenders)
235233

236234

237235
def compute_scs_0102_prop_image_description(images):
238236
"""This test ensures that each image has a proper value for the property `image_description`."""
239237
offenders = [img for img in images if not img.properties.get('image_description')]
240-
_log_error('property image_description not set', offenders)
241-
return not offenders
238+
return _log_error('property image_description not set', offenders)
242239

243240

244241
def compute_scs_0102_prop_replace_frequency(images, replace_frequencies=FREQ_TO_SEC):
245242
"""This test ensures that each image has a proper value for the property `replace_frequency`."""
246243
offenders = [img for img in images if img.properties.get('replace_frequency') not in replace_frequencies]
247-
_log_error('property replace_frequency not correct', offenders)
248-
return not offenders
244+
return _log_error('property replace_frequency not correct', offenders)
249245

250246

251247
def compute_scs_0102_prop_provided_until(images):
252248
"""This test ensures that each image has a proper value for the property `provided_until`."""
253249
offenders = [img for img in images if not img.properties.get('provided_until')]
254-
_log_error('property provided_until not set', offenders)
255-
return not offenders
250+
return _log_error('property provided_until not set', offenders)
256251

257252

258253
def compute_scs_0102_prop_uuid_validity(images):
259254
"""This test ensures that each image has a proper value for the property `uuid_validity`."""
260-
errors = 0
255+
offenders = []
261256
for img in images:
262257
img_uuid_val = img.properties.get("uuid_validity")
263258
if img_uuid_val in (None, "none", "notice", "forever"):
@@ -268,20 +263,20 @@ def compute_scs_0102_prop_uuid_validity(images):
268263
pass
269264
else:
270265
logger.error(f'Image "{img.name}": property uuid_validity INVALID: {img_uuid_val}')
271-
errors += 1
272-
return not errors
266+
offenders.append(img)
267+
return _log_error('uuid_validity INVALID', offenders, channel=logging.DEBUG)
273268

274269

275270
def compute_scs_0102_prop_hotfix_hours(images):
276271
"""This test ensures that each image has a proper value for the property `hotfix_hours`."""
277-
errors = 0
272+
offenders = []
278273
for img in images:
279274
hotfix_hours = img.properties.get("hotfix_hours", '')
280275
if not hotfix_hours or hotfix_hours.isdecimal():
281276
continue
282277
logger.error(f'Image "{img.name}": property hotfix_hours INVALID: {hotfix_hours}')
283-
errors += 1
284-
return not errors
278+
offenders.append(img)
279+
return _log_error('hotfix_hours INVALID', offenders, channel=logging.DEBUG)
285280

286281

287282
def _find_replacement_image(by_name, img_name):
@@ -310,7 +305,8 @@ def compute_scs_0102_image_recency(images):
310305
counter = Counter([img.name for img in images])
311306
duplicates = [name for name, count in counter.items() if count > 1]
312307
logger.warning(f'duplicate names detected: {", ".join(duplicates)}')
313-
errors = 0
308+
offenders1 = []
309+
offenders2 = []
314310
for img in images:
315311
# This is a bit tricky: We need to disregard images that have been rotated out
316312
# - os_hidden = True is a safe sign for this
@@ -319,17 +315,18 @@ def compute_scs_0102_image_recency(images):
319315
if not outd:
320316
continue # fine
321317
if outd == 3:
322-
logger.error(f'Image "{img.name}" does not provide a valid provided until date')
323-
errors += 1
318+
offenders1.append(img)
324319
continue # hopeless
325320
# in case that outd in (1, 2) try to find a non-outdated version
326321
if outd == 2:
327322
logger.warning(f'Image "{img.name}" seems outdated (acc. to its repl freq) but is not hidden or otherwise marked')
328323
# warnings += 1
329324
replacement = _find_replacement_image(by_name, img.name)
330325
if replacement is None:
331-
logger.error(f'Image "{img.name}" outdated without replacement')
332-
errors += 1
326+
offenders2.append(img)
333327
else:
334328
logger.info(f'Image "{replacement.name}" is a valid replacement for outdated "{img.name}"')
335-
return not errors
329+
return (
330+
_log_error('images w/o valid provided_until', offenders1, channel=logging.DEBUG) +
331+
_log_error('outdated images w/o replacement', offenders2, channel=logging.DEBUG)
332+
)

Tests/iaas/scs_0104_standard_images/standard_images.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,15 @@ def compute_scs_0104_source(image_lookup, image_spec):
7070
For an impression of what these specs look like, refer to `SCS_0104_IMAGE_SPECS`.
7171
"""
7272
matches = _lookup_images(image_lookup, image_spec)
73-
errors = 0
73+
errors = []
7474
for image in matches:
7575
img_source = image.properties.get('image_source', '')
7676
sources = image_spec['source']
7777
if not isinstance(sources, (tuple, list)):
7878
sources = [sources]
7979
if not any(img_source.startswith(src) for src in sources):
80-
errors += 1
81-
logger.error(f"Image '{image.name}' source mismatch: '{img_source}' matches none of these prefixes: {', '.join(sources)}")
82-
return not errors
80+
errors.append(f"Image '{image.name}' source mismatch: '{img_source}' matches none of these prefixes: {', '.join(sources)}")
81+
return errors
8382

8483

8584
def compute_scs_0104_image(image_lookup, image_spec):
@@ -89,7 +88,7 @@ def compute_scs_0104_image(image_lookup, image_spec):
8988
For an impression of what these specs look like, refer to `SCS_0104_IMAGE_SPECS`.
9089
"""
9190
matches = _lookup_images(image_lookup, image_spec)
91+
errors = []
9292
if not matches:
93-
logger.error(f"Missing image '{image_spec['name']}'")
94-
return False
95-
return True
93+
errors.append(f"Missing image '{image_spec['name']}'")
94+
return errors

0 commit comments

Comments
 (0)