Skip to content

Commit 771d370

Browse files
Merge branch 'cli1511' into update-250501
2 parents 213b572 + 843cecb commit 771d370

2 files changed

Lines changed: 86 additions & 2 deletions

File tree

src/mas/devops/mas.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import re
1313
import yaml
1414
from os import path
15+
from time import sleep
1516
from types import SimpleNamespace
1617
from kubernetes.dynamic.resource import ResourceInstance
1718
from openshift.dynamic import DynamicClient
@@ -194,3 +195,64 @@ def updateIBMEntitlementKey(dynClient: DynamicClient, namespace: str, icrUsernam
194195

195196
secret = secretsAPI.apply(body=secret, namespace=namespace)
196197
return secret
198+
199+
200+
def waitForPVC(dynClient: DynamicClient, namespace: str, pvcName: str) -> bool:
201+
pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim")
202+
maxRetries = 60
203+
foundReadyPVC = False
204+
retries = 0
205+
while not foundReadyPVC and retries < maxRetries:
206+
retries += 1
207+
try:
208+
pvc = pvcAPI.get(name=pvcName, namespace=namespace)
209+
if pvc.status.phase == "Bound":
210+
foundReadyPVC = True
211+
else:
212+
logger.debug("Waiting 5s for PVC {pvcName} to be ready before checking again ...")
213+
sleep(5)
214+
except NotFoundError:
215+
logger.debug("Waiting 5s for PVC {pvcName} to be created before checking again ...")
216+
sleep(5)
217+
218+
return foundReadyPVC
219+
220+
221+
def patchPendingPVC(dynClient: DynamicClient, namespace: str, pvcName: str, storageClassName: str = None) -> bool:
222+
pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim")
223+
try:
224+
pvc = pvcAPI.get(name=pvcName, namespace=namespace)
225+
if pvc.status.phase == "Pending" and pvc.spec.storageClassName is None:
226+
if storageClassName is not None and storageClassName(dynClient, name=storageClassName) is not None:
227+
pvc.spec.storageClassName = storageClassName
228+
else:
229+
defaultStorageClasses = getDefaultStorageClasses(dynClient)
230+
if defaultStorageClasses.provider is not None:
231+
pvc.spec.storageClassName = defaultStorageClasses.rwo
232+
else:
233+
logger.error("Unable to set storageClassName in PVC {pvcName}.")
234+
return False
235+
236+
pvcAPI.patch(body=pvc, namespace=namespace)
237+
238+
maxRetries = 60
239+
foundReadyPVC = False
240+
retries = 0
241+
while not foundReadyPVC and retries < maxRetries:
242+
retries += 1
243+
try:
244+
patchedPVC = pvcAPI.get(name=pvcName, namespace=namespace)
245+
if patchedPVC.status.phase == "Bound":
246+
foundReadyPVC = True
247+
else:
248+
logger.debug("Waiting 5s for PVC {pvcName} to be bound before checking again ...")
249+
sleep(5)
250+
except NotFoundError:
251+
logger.error("The patched PVC {pvcName} does not exist.")
252+
return False
253+
254+
return foundReadyPVC
255+
256+
except NotFoundError:
257+
logger.error("PVC {pvcName} does not exist")
258+
return False

src/mas/devops/tekton.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@
2323
from jinja2 import Environment, FileSystemLoader
2424

2525
from .ocp import getConsoleURL, waitForCRD, waitForDeployment, crdExists
26+
from .mas import waitForPVC, patchPendingPVC
2627

2728
logger = logging.getLogger(__name__)
2829

2930

30-
def installOpenShiftPipelines(dynClient: DynamicClient) -> bool:
31+
# customStorageClassName is used when no default Storageclass is available on cluster,
32+
# openshift-pipelines creates PVC which looks for default. customStorageClassName is patched into PVC when default is unavailable.
33+
def installOpenShiftPipelines(dynClient: DynamicClient, customStorageClassName: str = None) -> bool:
3134
"""
3235
Install the OpenShift Pipelines Operator and wait for it to be ready to use
3336
"""
@@ -79,11 +82,30 @@ def installOpenShiftPipelines(dynClient: DynamicClient) -> bool:
7982
foundReadyWebhook = waitForDeployment(dynClient, namespace="openshift-pipelines", deploymentName="tekton-pipelines-webhook")
8083
if foundReadyWebhook:
8184
logger.info("OpenShift Pipelines Webhook is installed and ready")
82-
return True
8385
else:
8486
logger.error("OpenShift Pipelines Webhook is NOT installed and ready")
8587
return False
8688

89+
# Wait for the postgredb-tekton-results-postgres-0 PVC to be ready
90+
# this PVC doesn't come up when there's no default storage class is in the cluster,
91+
# this is causing the pvc to be in pending state and causing the tekton-results-postgres statefulSet in pending,
92+
# due to these resources not coming up, the MAS pre-install check in the pipeline times out checking the health of this statefulSet,
93+
# causing failure in pipeline.
94+
# Refer https://github.com/ibm-mas/cli/issues/1511
95+
logger.debug("Waiting for postgredb-tekton-results-postgres-0 PVC to be ready")
96+
foundReadyPVC = waitForPVC(dynClient, namespace="openshift-pipelines", pvcName="postgredb-tekton-results-postgres-0")
97+
if foundReadyPVC:
98+
logger.info("OpenShift Pipelines postgres is installed and ready")
99+
return True
100+
else:
101+
patchedPVC = patchPendingPVC(dynClient, namespace="openshift-pipelines", pvcName="postgredb-tekton-results-postgres-0", storageClassName=customStorageClassName)
102+
if patchedPVC:
103+
logger.info("OpenShift Pipelines postgres is installed and ready")
104+
return True
105+
else:
106+
logger.error("OpenShift Pipelines postgres PVC is NOT ready")
107+
return False
108+
87109

88110
def updateTektonDefinitions(namespace: str, yamlFile: str) -> None:
89111
"""

0 commit comments

Comments
 (0)