From 4bbdb7c230bc27a0d9d113bf8a9ea342dd1a1901 Mon Sep 17 00:00:00 2001 From: David Parker Date: Wed, 17 Jul 2024 10:58:43 +0100 Subject: [PATCH] [patch] Wait for tekton-pipelines-webhook to be ready https://github.com/ibm-mas/cli/issues/1123 --- src/mas/devops/ocp.py | 27 ++++++++++++++++--- src/mas/devops/tekton.py | 22 ++++++++++----- .../templates/pipelinerun-install.yml.j2 | 9 ++++++- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/mas/devops/ocp.py b/src/mas/devops/ocp.py index 5ae405d5..f650e6cd 100644 --- a/src/mas/devops/ocp.py +++ b/src/mas/devops/ocp.py @@ -83,21 +83,40 @@ def waitForCRD(dynClient: DynamicClient, crdName: str) -> bool: while not foundReadyCRD and retries < maxRetries: retries += 1 try: - tasksCRD = crdAPI.get(name=crdName) - conditions = tasksCRD.status.conditions + crd = crdAPI.get(name=crdName) + conditions = crd.status.conditions for condition in conditions: if condition.type == "Established": if condition.status == "True": foundReadyCRD = True else: - logger.debug("Waiting 5s for tasks.tekton.dev CRD to be ready before checking again ...") + logger.debug(f"Waiting 5s for {crdName} CRD to be ready before checking again ...") sleep(5) continue except NotFoundError: - logger.debug("Waiting 5s for tasks.tekton.dev CRD to be installed before checking again ...") + logger.debug(f"Waiting 5s for {crdName} CRD to be installed before checking again ...") sleep(5) return foundReadyCRD +def waitForDeployment(dynClient: DynamicClient, namespace: str, deploymentName: str) -> bool: + deploymentAPI = dynClient.resources.get(api_version="apps/v1", kind="Deployment") + maxRetries = 100 + foundReadyDeployment = False + retries = 0 + while not foundReadyDeployment and retries < maxRetries: + retries += 1 + try: + deployment = deploymentAPI.get(name=deploymentName, namespace=namespace) + if deployment.status.readyReplicas > 0: + foundReadyDeployment = True + else: + logger.debug("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 ...") + sleep(5) + return foundReadyDeployment + def getConsoleURL(dynClient: DynamicClient) -> str: routesAPI = dynClient.resources.get(api_version="route.openshift.io/v1", kind="Route") diff --git a/src/mas/devops/tekton.py b/src/mas/devops/tekton.py index 23eddb37..0967da9d 100644 --- a/src/mas/devops/tekton.py +++ b/src/mas/devops/tekton.py @@ -22,7 +22,7 @@ from jinja2 import Environment, FileSystemLoader -from .ocp import getConsoleURL, waitForCRD +from .ocp import getConsoleURL, waitForCRD, waitForDeployment logger = logging.getLogger(__name__) @@ -61,14 +61,25 @@ def installOpenShiftPipelines(dynClient: DynamicClient) -> bool: except UnprocessibleEntityError: logger.warning("Error: Couldn't create/update OpenShift Pipelines Operator Subscription") + # Wait for the CRD to be available + logger.debug("Waiting for tasks.tekton.dev CRD to be available") foundReadyCRD = waitForCRD(dynClient, "tasks.tekton.dev") if foundReadyCRD: logger.info("OpenShift Pipelines Operator is installed and ready") - return True else: logger.error("OpenShift Pipelines Operator is NOT installed and ready") return False + # Wait for the webhook to be ready + logger.debug("Waiting for tekton-pipelines-webhook Deployment to be ready") + foundReadyWebhook = waitForDeployment(dynClient, namespace="openshift-pipelines", name="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 + def updateTektonDefinitions(namespace: str, yamlFile: str) -> None: """ Install/update the MAS tekton pipeline and task definitions @@ -143,7 +154,7 @@ def prepareInstallSecrets(dynClient: DynamicClient, instanceId: str, slsLicenseF pass if additionalConfigs is None: - additionalConfigs={ + additionalConfigs = { "apiVersion": "v1", "kind": "Secret", "type": "Opaque", @@ -174,7 +185,7 @@ def prepareInstallSecrets(dynClient: DynamicClient, instanceId: str, slsLicenseF pass if certs is None: - certs={ + certs = { "apiVersion": "v1", "kind": "Secret", "type": "Opaque", @@ -193,7 +204,7 @@ def prepareInstallSecrets(dynClient: DynamicClient, instanceId: str, slsLicenseF pass if podTemplates is None: - podTemplates={ + podTemplates = { "apiVersion": "v1", "kind": "Secret", "type": "Opaque", @@ -315,7 +326,6 @@ def launchUninstallPipeline(dynClient: DynamicClient, pipelineURL = f"{getConsoleURL(dynClient)}/k8s/ns/mas-{instanceId}-pipelines/tekton.dev~v1beta1~PipelineRun/{instanceId}-uninstall-{timestamp}" return pipelineURL - def launchPipelineRun(dynClient: DynamicClient, namespace: str, templateName: str, params: dict) -> str: pipelineRunsAPI = dynClient.resources.get(api_version="tekton.dev/v1beta1", kind="PipelineRun") timestamp = datetime.now().strftime("%y%m%d-%H%M") diff --git a/src/mas/devops/templates/pipelinerun-install.yml.j2 b/src/mas/devops/templates/pipelinerun-install.yml.j2 index d05235bc..727b7196 100644 --- a/src/mas/devops/templates/pipelinerun-install.yml.j2 +++ b/src/mas/devops/templates/pipelinerun-install.yml.j2 @@ -25,6 +25,13 @@ spec: - name: skip_pre_check value: "{{ skip_pre_check }}" {%- endif %} +{%- if image_pull_policy is defined and image_pull_policy != "" %} + + # Image Pull Policy + # ------------------------------------------------------------------------- + - name: image_pull_policy + value: "{{ image_pull_policy }}" +{%- endif %} {%- if ocp_ingress_tls_secret_name is defined and ocp_ingress_tls_secret_name != "" %} # Cluster config @@ -32,7 +39,7 @@ spec: - name: ocp_ingress_tls_secret_name value: "{{ ocp_ingress_tls_secret_name }}" {%- endif %} -{%- if artifactory_username is defined and artifactory_token != "" %} +{%- if artifactory_username is defined and artifactory_username != "" %} # Enable development catalogs # -------------------------------------------------------------------------