Skip to content

Commit 2533643

Browse files
committed
validate: validate csv spec.crd.owned & descriptors
spec.customresourcedefinitions.owned CRDs must have displayName and description and values must not be empty. Validate the attributes of csv owned crd descriptors.
1 parent e996be2 commit 2533643

File tree

6 files changed

+1371
-63
lines changed

6 files changed

+1371
-63
lines changed

operatorcourier/validate.py

Lines changed: 136 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -184,79 +184,127 @@ def _csv_spec_validation(self, spec, bundleData):
184184
valid = False
185185

186186
if "customresourcedefinitions" in spec:
187-
customresourcedefinitions = spec["customresourcedefinitions"]
187+
if self._csv_crd_validation(
188+
spec["customresourcedefinitions"], bundleData) is False:
189+
valid = False
188190

189-
crdList = []
190-
for crd in bundleData[self.crdKey]:
191-
try:
192-
name = crd["metadata"]["name"]
193-
crdList.append(name)
194-
except KeyError:
195-
pass
191+
return valid
196192

197-
if "owned" not in customresourcedefinitions:
198-
self._log_error("spec.customresourcedefinitions.owned"
199-
"not defined for csv")
200-
return False
193+
def _csv_crd_validation(self, customresourcedefinitions, bundleData):
194+
valid = True
201195

202-
for csvOwnedCrd in customresourcedefinitions["owned"]:
203-
if "name" not in csvOwnedCrd:
204-
self._log_error("name not defined for item in "
205-
"spec.customresourcedefinitions.")
206-
valid = False
207-
elif csvOwnedCrd["name"] not in crdList:
208-
self._log_error("custom resource definition %s referenced in csv "
209-
"not defined in root list of crds",
210-
csvOwnedCrd["name"])
196+
crdList = []
197+
for crd in bundleData[self.crdKey]:
198+
try:
199+
name = crd["metadata"]["name"]
200+
crdList.append(name)
201+
except KeyError:
202+
pass
203+
204+
if "owned" not in customresourcedefinitions:
205+
self._log_error("spec.customresourcedefinitions.owned"
206+
"not defined for csv")
207+
return False
208+
209+
for csvOwnedCrd in customresourcedefinitions["owned"]:
210+
if "name" not in csvOwnedCrd:
211+
self._log_error("name not defined for item in "
212+
"spec.customresourcedefinitions.")
213+
valid = False
214+
elif csvOwnedCrd["name"] not in crdList:
215+
self._log_error("custom resource definition %s referenced in csv "
216+
"not defined in root list of crds",
217+
csvOwnedCrd["name"])
218+
valid = False
219+
220+
if "kind" not in csvOwnedCrd:
221+
self._log_error("kind not defined for item in "
222+
"spec.customresourcedefinitions.")
223+
valid = False
224+
if "version" not in csvOwnedCrd:
225+
self._log_error("version not defined for item in "
226+
"spec.customresourcedefinitions.")
227+
valid = False
228+
229+
# Values of name, version and kind above are compared with their
230+
# values in the associated CRD files later. Empty string check
231+
# is not needed.
232+
# displayName and description should be checked for empty
233+
# strings.
234+
if "displayName" not in csvOwnedCrd:
235+
self._log_error("displayName not defined for item in "
236+
"spec.customresourcedefinitions.")
237+
valid = False
238+
elif not csvOwnedCrd["displayName"]:
239+
self._log_error("displayName is empty for item in "
240+
"spec.customresourcedefinitions.")
241+
valid = False
242+
if "description" not in csvOwnedCrd:
243+
self._log_error("description not defined for item in "
244+
"spec.customresourcedefinitions.")
245+
valid = False
246+
elif not csvOwnedCrd["description"]:
247+
self._log_error("description is empty for item in "
248+
"spec.customresourcedefinitions.")
249+
valid = False
250+
251+
if "specDescriptors" in csvOwnedCrd and "name" in csvOwnedCrd:
252+
if self._csv_descriptors_validation(
253+
csvOwnedCrd["specDescriptors"],
254+
csvOwnedCrd["name"]) is False:
211255
valid = False
212256

213-
if "kind" not in csvOwnedCrd:
214-
self._log_error("kind not defined for item in "
215-
"spec.customresourcedefinitions.")
257+
if "statusDescriptors" in csvOwnedCrd and "name" in csvOwnedCrd:
258+
if self._csv_descriptors_validation(
259+
csvOwnedCrd["statusDescriptors"],
260+
csvOwnedCrd["name"]) is False:
216261
valid = False
217-
if "version" not in csvOwnedCrd:
218-
self._log_error("version not defined for item in "
219-
"spec.customresourcedefinitions.")
262+
263+
if "actionDescriptors" in csvOwnedCrd and "name" in csvOwnedCrd:
264+
if self._csv_descriptors_validation(
265+
csvOwnedCrd["actionDescriptors"],
266+
csvOwnedCrd["name"]) is False:
220267
valid = False
221268

222-
for crd in bundleData[self.crdKey]:
223-
if 'name' not in csvOwnedCrd:
224-
continue
225-
if 'metadata' not in crd or 'name' not in crd['metadata']:
226-
continue
227-
if csvOwnedCrd['name'] != crd['metadata']['name']:
228-
continue
229-
230-
if 'kind' in csvOwnedCrd:
231-
if 'spec' in crd:
232-
if 'names' in crd['spec']:
233-
if 'kind' in crd['spec']['names']:
234-
if csvOwnedCrd['kind'] != \
235-
crd['spec']['names']['kind']:
236-
self._log_error('CRD.spec.names.kind does not '
237-
'match CSV.spec.crd.owned.kind')
238-
valid = False
239-
240-
if 'version' in csvOwnedCrd:
241-
if 'spec' in crd:
242-
if 'version' in crd['spec']:
243-
if csvOwnedCrd['version'] != crd['spec']['version']:
244-
self._log_error('CRD.spec.version does not match '
245-
'CSV.spec.crd.owned.version')
269+
for crd in bundleData[self.crdKey]:
270+
if 'name' not in csvOwnedCrd:
271+
continue
272+
if 'metadata' not in crd or 'name' not in crd['metadata']:
273+
continue
274+
if csvOwnedCrd['name'] != crd['metadata']['name']:
275+
continue
276+
277+
if 'kind' in csvOwnedCrd:
278+
if 'spec' in crd:
279+
if 'names' in crd['spec']:
280+
if 'kind' in crd['spec']['names']:
281+
if csvOwnedCrd['kind'] != \
282+
crd['spec']['names']['kind']:
283+
self._log_error('CRD.spec.names.kind does not '
284+
'match CSV.spec.crd.owned.kind')
285+
valid = False
286+
287+
if 'version' in csvOwnedCrd:
288+
if 'spec' in crd:
289+
if 'version' in crd['spec']:
290+
if csvOwnedCrd['version'] != crd['spec']['version']:
291+
self._log_error('CRD.spec.version does not match '
292+
'CSV.spec.crd.owned.version')
293+
valid = False
294+
295+
if 'name' in csvOwnedCrd:
296+
if 'spec' in crd:
297+
if 'names' in crd['spec'] and 'group' in crd['spec']:
298+
if 'plural' in crd['spec']['names']:
299+
if csvOwnedCrd['name'] != \
300+
crd['spec']['names']['plural'] + '.' + \
301+
crd['spec']['group']:
302+
self._log_error("`CRD.spec.names.plural`."
303+
"`CRD.spec.group` does not "
304+
"match "
305+
"CSV.spec.crd.owned.name")
246306
valid = False
247307

248-
if 'name' in csvOwnedCrd:
249-
if 'spec' in crd:
250-
if 'names' in crd['spec'] and 'group' in crd['spec']:
251-
if 'plural' in crd['spec']['names']:
252-
if csvOwnedCrd['name'] != \
253-
crd['spec']['names']['plural'] + '.' + \
254-
crd['spec']['group']:
255-
self._log_error("`CRD.spec.names.plural`."
256-
"`CRD.spec.group` does not "
257-
"match "
258-
"CSV.spec.crd.owned.name")
259-
valid = False
260308
return valid
261309

262310
def _csv_spec_install_validation(self, install):
@@ -312,6 +360,31 @@ def _csv_spec_install_validation(self, install):
312360

313361
return valid
314362

363+
def _csv_descriptors_validation(self, descriptors, crdName):
364+
valid = True
365+
366+
# required attributes of descriptors
367+
attributeList = ["displayName", "description", "path"]
368+
369+
# validate a descriptor for a given attribute
370+
def validate_descriptor(descriptor, resourceName, attribute):
371+
if attribute not in descriptor:
372+
self._log_error("%s is not defined for descriptors in %s"
373+
% (attribute, resourceName))
374+
return False
375+
elif not descriptor[attribute]:
376+
self._log_error("%s is empty for descriptors in %s"
377+
% (attribute, resourceName))
378+
return False
379+
return True
380+
381+
for desc in descriptors:
382+
for attr in attributeList:
383+
if validate_descriptor(desc, crdName, attr) is False:
384+
valid = False
385+
386+
return valid
387+
315388
def _csv_metadata_validation(self, metadata):
316389
valid = True
317390

0 commit comments

Comments
 (0)