Blob Blame History Raw
From 6183101985e7c3c83c13aa5c7eb7545bccc8953b Mon Sep 17 00:00:00 2001
From: Simone Tiraboschi <stirabos@redhat.com>
Date: Mon, 13 Jul 2020 23:31:05 +0200
Subject: [PATCH] Correctly validate crd.spec.versions

crd.spec.version got deprecated for crd.spec.versions
but in this case we are going to access a list of
dictionaries where the relevant value
is in the name field.

Fix all the validations on spec.versions and add
additional validations.

Fix also its test.

Signed-off-by: Simone Tiraboschi stirabos@redhat.com
Fixes: #188
---
 operatorcourier/validate.py                   | 56 +++++++++++++++++--
 .../crdversions.invalid.bundle.yaml           |  4 +-
 .../crdversions.valid.bundle.yaml             |  8 ++-
 3 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/operatorcourier/validate.py b/operatorcourier/validate.py
index 2a4a4fa..9644aa7 100644
--- a/operatorcourier/validate.py
+++ b/operatorcourier/validate.py
@@ -156,11 +156,52 @@ def _crd_validation(self, bundle):
                 if "group" not in crd['spec']:
                     self._log_error("crd spec.group not defined.")
                     valid = False
-                if "versions" not in crd['spec']:
-                    if "version" not in crd['spec']:
-                        self._log_error("crd spec.version or spec.versions not defined")
+                if (
+                    "versions" not in crd['spec'] and
+                    "version" not in crd['spec']
+                ):
+                    self._log_error(
+                        "crd spec.version or spec.versions not defined."
+                    )
+                    valid = False
+                if "versions" in crd['spec']:
+                    if not len(crd['spec']['versions']) > 0:
+                        self._log_error("crd spec.versions is empty.")
                         valid = False
-
+                    else:
+                        for ver in crd['spec']['versions']:
+                            if (
+                                "name" not in ver or
+                                "served" not in ver or
+                                "storage" not in ver
+                            ):
+                                self._log_error(
+                                    "crd spec.versions contains an invalid "
+                                    "CustomResourceDefinitionVersion."
+                                )
+                                valid = False
+                        if "version" in crd['spec']:
+                            if (
+                                "name" in crd['spec']['version'][0] and
+                                crd['spec']['version'][0]['name'] !=
+                                crd['spec']['version']
+                            ):
+                                self._log_error(
+                                    "crd spec.version and spec.versions are "
+                                    "defined but spec.versions[0].name "
+                                    "doesn't match spec.version."
+                                )
+                                valid = False
+                        storage_version_list = [
+                            v for v in crd['spec']['versions']
+                            if "storage" in v and v['storage'] is True
+                        ]
+                        if len(storage_version_list) != 1:
+                            self._log_error(
+                                "crd spec.version should contain exactly "
+                                "one version flagged as storage version."
+                            )
+                            valid = False
         return valid
 
     def _csv_validation(self, bundle):
@@ -273,8 +314,11 @@ def _csv_spec_validation(self, spec, bundleData):
                     if 'version' in csvOwnedCrd:
                         if 'spec' in crd:
                             if 'versions' in crd['spec']:
-                                if csvOwnedCrd['version'] not in crd['spec']['versions']:
-                                    self._log_error('CSV.spec.crd.owned.version is'
+                                if csvOwnedCrd['version'] not in [
+                                    v['name'] for v in crd['spec']['versions']
+                                    if 'name' in v
+                                ]:
+                                    self._log_error('CSV.spec.crd.owned.version is '
                                                     'not in CRD.spec.versions list')
                                     valid = False
                             if 'version' in crd['spec']:
diff --git a/tests/test_files/bundles/verification/crdversions.invalid.bundle.yaml b/tests/test_files/bundles/verification/crdversions.invalid.bundle.yaml
index 1512e96..63bce44 100644
--- a/tests/test_files/bundles/verification/crdversions.invalid.bundle.yaml
+++ b/tests/test_files/bundles/verification/crdversions.invalid.bundle.yaml
@@ -263,7 +263,9 @@ data:
                 - packages
                 type: object
         versions:
-        - v1beta1
+        - name: v1beta1
+          served: true
+          storage: true
     - apiVersion: apiextensions.k8s.io/v1beta1
       kind: CustomResourceDefinition
       metadata:
diff --git a/tests/test_files/bundles/verification/crdversions.valid.bundle.yaml b/tests/test_files/bundles/verification/crdversions.valid.bundle.yaml
index 92f4c7a..311fa8f 100644
--- a/tests/test_files/bundles/verification/crdversions.valid.bundle.yaml
+++ b/tests/test_files/bundles/verification/crdversions.valid.bundle.yaml
@@ -263,8 +263,12 @@ data:
                 - packages
                 type: object
         versions:
-        - v1alpha1
-        - v1beta1
+        - name: v1beta1
+          served: true
+          storage: true
+        - name: v1alpha1
+          served: true
+          storage: false
     - apiVersion: apiextensions.k8s.io/v1beta1
       kind: CustomResourceDefinition
       metadata: