diff --git a/src/mas/devops/data/catalogs/v9-250501-amd64.yaml b/src/mas/devops/data/catalogs/v9-250501-amd64.yaml new file mode 100644 index 00000000..cc3bd7c7 --- /dev/null +++ b/src/mas/devops/data/catalogs/v9-250501-amd64.yaml @@ -0,0 +1,111 @@ +--- +# Case bundle configuration for IBM Maximo Operator Catalog 250501 +# ----------------------------------------------------------------------------- +# In the future this won't be necessary as we'll be able to mirror from the +# catalog itself, but not everything in the catalog supports this yet (including MAS) +# so we need to use the CASE bundle mirror process still. + +catalog_digest: sha256:5121d783b8f59d35d32d6bf6cdbfe63f79b81f7f330016d07d5b58609171ccab + +# Dependencies +# ----------------------------------------------------------------------------- +ibm_licensing_version: 4.2.12 # Operator version 4.2.11 (https://github.com/IBM/cloud-pak/tree/master/repo/case/ibm-licensing) +common_svcs_version: 4.7.0 # check once why we have 4.3.0 in all previous versions since so long it's 4.3.0 # Operator version 4.3.1 (https://github.com/IBM/cloud-pak/tree/master/repo/case/ibm-cp-common-services) +common_svcs_version_2: 4.8.0 +common_svcs_version_1: 4.3.0 #+20240702.100000 # common_svcs is a mess + +cp4d_platform_version: 5.0.0 #+20240716.101015 # Operator version 5.0.0 (https://github.com/IBM/cloud-pak/tree/master/repo/case/ibm-cp-datacore/4.0.0%2B20231213.115030) + +ibm_zen_version: 6.0.1+20240708.121250.32 # For CPD5 ibm-zen has to be explicitily mirrored + +db2u_version: 6.0.1+20240704.142950.9960 # Operator version 110509.0.2 to find the version 6.0.1, search CASE_VERSION in db2u, catalog.yaml into ibm-maximo-operator-catalog (https://github.com/IBM/cloud-pak/tree/master/repo/case/ibm-db2uoperator) +events_version: 5.0.1 # Operator version 5.0.1 (https://github.com/IBM/cloud-pak/tree/master/repo/case/ibm-events-operator) +uds_version: 2.0.12 # Operator version 2.0.12 # sticking to 2.0.12 version # Please do Not Change +sls_version: 3.11.1 # tbc # Operator version 3.10.0 (https://github.ibm.com/maximoappsuite/ibm-sls/releases) +tsm_version: 1.6.2 # tbc # Operator version 1.5.4 (https://github.ibm.com/maximoappsuite/ibm-truststore-mgr/releases) +dd_version: 1.1.18 # tbc # Operator version 1.1.14 (https://github.ibm.com/maximoappsuite/ibm-data-dictionary/releases) +appconnect_version: 6.2.0 # Operator version 6.2.0 # sticking to 6.2.0 version # Please do Not Change +wsl_version: 9.0.0 # Operator version 9.0.0 +wml_version: 9.0.0 # Operator version 5.0.0 +# ccs_build: +20240528.144404.460 # ibm-ccs from version 9.0.0 requires the build version +# datarefinery_build: +20240517.202103.146 +spark_version: 9.0.0 # Operator version 5.0.0 +cognos_version: 25.0.0 # Operator version 25.0.0 +couchdb_version: 1.0.13 # Operator version 2.2.1 (This is required for Assist 9.0, https://github.com/IBM/cloud-pak/blob/master/repo/case/ibm-couchdb/index.yaml) +elasticsearch_version: 1.1.2570 # Operator version 1.1.2470 + + +# Maximo Application Suite +# ----------------------------------------------------------------------------- +mas_core_version: + 9.1.x-feature: 9.1.0-pre.stable_9718 # No Update + 9.0.x: 9.0.11 # tbc + 8.10.x: 8.10.25 # tbc + 8.11.x: 8.11.22 # tbc +mas_assist_version: + 9.0.x: 9.0.5 # No Update + 8.10.x: 8.7.8 # No Update + 8.11.x: 8.8.7 # No Update +mas_hputilities_version: + 9.0.x: "" # Not Supported + 8.10.x: 8.6.7 # tbc + 8.11.x: "" # Not Supported +mas_iot_version: + 9.0.x: 9.0.8 # tbc + 8.10.x: 8.7.22 # tbc + 8.11.x: 8.8.18 # tbc +mas_manage_version: + 9.1.x-feature: 9.1.0-pre.stable_10993 # No Update + 9.0.x: 9.0.13 # tbc + 8.10.x: 8.6.26 # tbc + 8.11.x: 8.7.20 # tbc +mas_monitor_version: + 9.0.x: 9.0.9 # tbc + 8.10.x: 8.10.19 # tbc + 8.11.x: 8.11.17 # tbc +mas_optimizer_version: + 9.1.x-feature: 9.1.0-pre.stable_1943 # No Update + 9.0.x: 9.0.10 # tbc + 8.10.x: 8.4.17 # tbc + 8.11.x: 8.5.16 # tbc +mas_predict_version: + 9.0.x: 9.0.7 # tbc + 8.10.x: 8.8.8 # tbc + 8.11.x: 8.9.10 # tbc +mas_visualinspection_version: + 9.1.x-feature: 9.1.0-pre.stable_2405 # No Update + 9.0.x: 9.0.9 # tbc + 8.10.x: 8.8.4 # No Update + 8.11.x: 8.9.12 # tbc + +# Extra Images for UDS +# ------------------------------------------------------------------------------ +uds_extras_version: 1.5.0 + +# Extra Images for Mongo +# ------------------------------------------------------------------------------ +mongo_extras_version_default: 7.0.12 + +# Variables used to mirror additional mongo image versions +mongo_extras_version_4: 4.4.21 +mongo_extras_version_5: 5.0.23 +mongo_extras_version_6: 6.0.12 +mongo_extras_version_7: 7.0.12 + +# Extra Images for Db2u +# ------------------------------------------------------------------------------ +db2u_extras_version: 1.0.6 # No Update +db2u_filter: db2 + +# Extra Images for IBM Watson Discovery +# ------------------------------------------------------------------------------ +#wd_extras_version: 1.0.4 + +# Extra Images for Amlen +# ------------------------------------------------------------------------------ +amlen_extras_version: 1.1.2 + +# Default Cloud Pak for Data version +# ------------------------------------------------------------------------------ +cpd_product_version_default: 5.0.0 + diff --git a/src/mas/devops/data/catalogs/v9-250501-s390x.yaml b/src/mas/devops/data/catalogs/v9-250501-s390x.yaml new file mode 100644 index 00000000..7594c932 --- /dev/null +++ b/src/mas/devops/data/catalogs/v9-250501-s390x.yaml @@ -0,0 +1,40 @@ +--- +# Case bundle configuration for IBM Maximo Operator Catalog 250501 +# ----------------------------------------------------------------------------- +# In the future this won't be necessary as we'll be able to mirror from the +# catalog itself, but not everything in the catalog supports this yet (including MAS) +# so we need to use the CASE bundle mirror process still. + +catalog_digest: sha256:101f126494d4840f7cda7aa87b30d49aafd9abf736d455bf65597f0b35b1c070 + +uds_version: 2.0.12 # Operator version 2.0.12 # sticking to 2.0.12 version # Please do Not Change +sls_version: 3.11.1 # tbc # Operator version 3.10.0 (https://github.ibm.com/maximoappsuite/ibm-sls/releases) +tsm_version: 1.6.2 # No Update # Operator version 1.5.4 (https://github.ibm.com/maximoappsuite/ibm-truststore-mgr/releases) + + +# Maximo Application Suite +# ----------------------------------------------------------------------------- +mas_core_version: + 9.1.x-feature: 9.1.0-pre.stable_9718 # tbc + 9.0.x: 9.0.11 # tbc + 8.10.x: "" # Not Supported + 8.11.x: "" # Not Supported +mas_manage_version: + 9.1.x-feature: 9.1.0-pre.stable_10993 # tbc + 9.0.x: 9.0.13 # tbc + 8.10.x: "" # Not Supported + 8.11.x: "" # Not Supported + +# Extra Images for UDS +# ------------------------------------------------------------------------------ +uds_extras_version: 1.5.0 + +# Extra Images for Mongo +# ------------------------------------------------------------------------------ +mongo_extras_version_default: 7.0.12 + +# Variables used to mirror additional mongo image versions +mongo_extras_version_4: 4.4.21 +mongo_extras_version_5: 5.0.23 +mongo_extras_version_6: 6.0.12 +mongo_extras_version_7: 7.0.12 diff --git a/src/mas/devops/mas.py b/src/mas/devops/mas.py index e2e0cbd5..ac207574 100644 --- a/src/mas/devops/mas.py +++ b/src/mas/devops/mas.py @@ -12,6 +12,7 @@ import re import yaml from os import path +from time import sleep from types import SimpleNamespace from kubernetes.dynamic.resource import ResourceInstance from openshift.dynamic import DynamicClient @@ -159,8 +160,8 @@ def verifyMasInstance(dynClient: DynamicClient, instanceId: str) -> bool: except ResourceNotFoundError: # The MAS Suite CRD has not even been installed in the cluster return False - except UnauthorizedError: - logger.error("Error: Unable to verify MAS instance due to failed authorization: {e}") + except UnauthorizedError as e: + logger.error(f"Error: Unable to verify MAS instance due to failed authorization: {e}") return False @@ -243,3 +244,64 @@ def updateIBMEntitlementKey(dynClient: DynamicClient, namespace: str, icrUsernam secret = secretsAPI.apply(body=secret, namespace=namespace) return secret + + +def waitForPVC(dynClient: DynamicClient, namespace: str, pvcName: str) -> bool: + pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim") + maxRetries = 60 + foundReadyPVC = False + retries = 0 + while not foundReadyPVC and retries < maxRetries: + retries += 1 + try: + pvc = pvcAPI.get(name=pvcName, namespace=namespace) + if pvc.status.phase == "Bound": + foundReadyPVC = True + else: + logger.debug(f"Waiting 5s for PVC {pvcName} to be ready before checking again ...") + sleep(5) + except NotFoundError: + logger.debug(f"Waiting 5s for PVC {pvcName} to be created before checking again ...") + sleep(5) + + return foundReadyPVC + + +def patchPendingPVC(dynClient: DynamicClient, namespace: str, pvcName: str, storageClassName: str = None) -> bool: + pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim") + try: + pvc = pvcAPI.get(name=pvcName, namespace=namespace) + if pvc.status.phase == "Pending" and pvc.spec.storageClassName is None: + if storageClassName is not None and storageClassName(dynClient, name=storageClassName) is not None: + pvc.spec.storageClassName = storageClassName + else: + defaultStorageClasses = getDefaultStorageClasses(dynClient) + if defaultStorageClasses.provider is not None: + pvc.spec.storageClassName = defaultStorageClasses.rwo + else: + logger.error(f"Unable to set storageClassName in PVC {pvcName}.") + return False + + pvcAPI.patch(body=pvc, namespace=namespace) + + maxRetries = 60 + foundReadyPVC = False + retries = 0 + while not foundReadyPVC and retries < maxRetries: + retries += 1 + try: + patchedPVC = pvcAPI.get(name=pvcName, namespace=namespace) + if patchedPVC.status.phase == "Bound": + foundReadyPVC = True + else: + logger.debug(f"Waiting 5s for PVC {pvcName} to be bound before checking again ...") + sleep(5) + except NotFoundError: + logger.error(f"The patched PVC {pvcName} does not exist.") + return False + + return foundReadyPVC + + except NotFoundError: + logger.error(f"PVC {pvcName} does not exist") + return False diff --git a/src/mas/devops/ocp.py b/src/mas/devops/ocp.py index 2aa9e0b9..e4c54113 100644 --- a/src/mas/devops/ocp.py +++ b/src/mas/devops/ocp.py @@ -150,10 +150,10 @@ def waitForDeployment(dynClient: DynamicClient, namespace: str, deploymentName: # NoneType and int comparison TypeError foundReadyDeployment = True else: - logger.debug("Waiting 5s for deployment {deploymentName} to be ready before checking again ...") + logger.debug(f"Waiting 5s for deployment {deploymentName} to be ready before checking again ...") sleep(5) except NotFoundError: - logger.debug("Waiting 5s for deployment {deploymentName} to be created before checking again ...") + logger.debug(f"Waiting 5s for deployment {deploymentName} to be created before checking again ...") sleep(5) return foundReadyDeployment diff --git a/src/mas/devops/tekton.py b/src/mas/devops/tekton.py index bd109093..c2e09a3e 100644 --- a/src/mas/devops/tekton.py +++ b/src/mas/devops/tekton.py @@ -23,11 +23,14 @@ from jinja2 import Environment, FileSystemLoader from .ocp import getConsoleURL, waitForCRD, waitForDeployment, crdExists +from .mas import waitForPVC, patchPendingPVC logger = logging.getLogger(__name__) -def installOpenShiftPipelines(dynClient: DynamicClient) -> bool: +# customStorageClassName is used when no default Storageclass is available on cluster, +# openshift-pipelines creates PVC which looks for default. customStorageClassName is patched into PVC when default is unavailable. +def installOpenShiftPipelines(dynClient: DynamicClient, customStorageClassName: str = None) -> bool: """ Install the OpenShift Pipelines Operator and wait for it to be ready to use """ @@ -79,11 +82,30 @@ def installOpenShiftPipelines(dynClient: DynamicClient) -> bool: foundReadyWebhook = waitForDeployment(dynClient, namespace="openshift-pipelines", deploymentName="tekton-pipelines-webhook") if foundReadyWebhook: logger.info("OpenShift Pipelines Webhook is installed and ready") - return True else: logger.error("OpenShift Pipelines Webhook is NOT installed and ready") return False + # Wait for the postgredb-tekton-results-postgres-0 PVC to be ready + # this PVC doesn't come up when there's no default storage class is in the cluster, + # this is causing the pvc to be in pending state and causing the tekton-results-postgres statefulSet in pending, + # due to these resources not coming up, the MAS pre-install check in the pipeline times out checking the health of this statefulSet, + # causing failure in pipeline. + # Refer https://github.com/ibm-mas/cli/issues/1511 + logger.debug("Waiting for postgredb-tekton-results-postgres-0 PVC to be ready") + foundReadyPVC = waitForPVC(dynClient, namespace="openshift-pipelines", pvcName="postgredb-tekton-results-postgres-0") + if foundReadyPVC: + logger.info("OpenShift Pipelines postgres is installed and ready") + return True + else: + patchedPVC = patchPendingPVC(dynClient, namespace="openshift-pipelines", pvcName="postgredb-tekton-results-postgres-0", storageClassName=customStorageClassName) + if patchedPVC: + logger.info("OpenShift Pipelines postgres is installed and ready") + return True + else: + logger.error("OpenShift Pipelines postgres PVC is NOT ready") + return False + def updateTektonDefinitions(namespace: str, yamlFile: str) -> None: """ diff --git a/test/src/test_data.py b/test/src/test_data.py index ffec3890..f45d8943 100644 --- a/test/src/test_data.py +++ b/test/src/test_data.py @@ -26,7 +26,7 @@ def test_list_catalogs(): def test_get_newest_catalog_tag(): catalogTag = getNewestCatalogTag("amd64") # Reminder: update this test when adding a new catalog each month! - assert catalogTag == "v9-250403-amd64" + assert catalogTag == "v9-250501-amd64" def test_get_newest_catalog_tag_fail():