Skip to content

Commit 53b59a2

Browse files
committed
[patch] Fix PVC storage class patching for OpenShift Pipelines
1 parent e93c898 commit 53b59a2

1 file changed

Lines changed: 41 additions & 6 deletions

File tree

src/mas/devops/tekton.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
from jinja2 import Environment, FileSystemLoader
2424

25-
from .ocp import getConsoleURL, waitForCRD, waitForDeployment, crdExists, waitForPVC
25+
from .ocp import getConsoleURL, waitForCRD, waitForDeployment, crdExists, waitForPVC, getStorageClasses
2626

2727
logger = logging.getLogger(__name__)
2828

@@ -111,7 +111,7 @@ def installOpenShiftPipelines(dynClient: DynamicClient, customStorageClassName:
111111
return False
112112

113113

114-
def addMissingStorageClassToTektonPVC(dynClient: DynamicClient, namespace: str, pvcName: str, storageClassName: str) -> bool:
114+
def addMissingStorageClassToTektonPVC(dynClient: DynamicClient, namespace: str, pvcName: str, storageClassName: str = None) -> bool:
115115
"""
116116
OpenShift Pipelines has a problem when there is no default storage class defined in a cluster, this function
117117
patches the PVC used to store pipeline results to add a specific storage class into the PVC spec and waits for the
@@ -123,18 +123,49 @@ def addMissingStorageClassToTektonPVC(dynClient: DynamicClient, namespace: str,
123123
:type namespace: str
124124
:param pvcName: Name of the PVC that we want to fix
125125
:type pvcName: str
126-
:param storageClassName: Name of the storage class that we want to update the PVC to reference
126+
:param storageClassName: Name of the storage class that we want to update the PVC to reference (optional, will auto-select if not provided)
127127
:type storageClassName: str
128-
:return: Description
128+
:return: True if PVC is successfully patched and bound, False otherwise
129129
:rtype: bool
130130
"""
131131
pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim")
132+
storageClassAPI = dynClient.resources.get(api_version="storage.k8s.io/v1", kind="StorageClass")
133+
132134
try:
133135
pvc = pvcAPI.get(name=pvcName, namespace=namespace)
136+
137+
# Check if PVC is pending and has no storage class
134138
if pvc.status.phase == "Pending" and pvc.spec.storageClassName is None:
135-
pvc.spec.storageClassName = storageClassName
139+
# Determine which storage class to use
140+
targetStorageClass = None
141+
142+
if storageClassName is not None:
143+
# Verify the provided storage class exists
144+
try:
145+
storageClassAPI.get(name=storageClassName)
146+
targetStorageClass = storageClassName
147+
logger.info(f"Using provided storage class '{storageClassName}' for PVC {pvcName}")
148+
except NotFoundError:
149+
logger.warning(f"Provided storage class '{storageClassName}' not found, will try to detect available storage class")
150+
151+
# If no valid custom storage class, try to detect one
152+
if targetStorageClass is None:
153+
logger.warning("No storage class provided or provided storage class not found, attempting to use first available storage class")
154+
storageClasses = getStorageClasses(dynClient)
155+
if len(storageClasses) > 0:
156+
# Use the first available storage class
157+
targetStorageClass = storageClasses[0].metadata.name
158+
logger.info(f"Using first available storage class '{targetStorageClass}' for PVC {pvcName}")
159+
else:
160+
logger.error(f"Unable to set storageClassName in PVC {pvcName}. No storage classes available in the cluster.")
161+
return False
162+
163+
# Patch the PVC with the storage class
164+
pvc.spec.storageClassName = targetStorageClass
165+
logger.info(f"Patching PVC {pvcName} with storageClassName: {targetStorageClass}")
136166
pvcAPI.patch(body=pvc, namespace=namespace)
137167

168+
# Wait for the PVC to be bound
138169
maxRetries = 60
139170
foundReadyPVC = False
140171
retries = 0
@@ -144,6 +175,7 @@ def addMissingStorageClassToTektonPVC(dynClient: DynamicClient, namespace: str,
144175
patchedPVC = pvcAPI.get(name=pvcName, namespace=namespace)
145176
if patchedPVC.status.phase == "Bound":
146177
foundReadyPVC = True
178+
logger.info(f"PVC {pvcName} is now bound")
147179
else:
148180
logger.debug(f"Waiting 5s for PVC {pvcName} to be bound before checking again ...")
149181
sleep(5)
@@ -152,6 +184,9 @@ def addMissingStorageClassToTektonPVC(dynClient: DynamicClient, namespace: str,
152184
return False
153185

154186
return foundReadyPVC
187+
else:
188+
logger.warning(f"PVC {pvcName} is not in Pending state or already has a storageClassName")
189+
return pvc.status.phase == "Bound"
155190

156191
except NotFoundError:
157192
logger.error(f"PVC {pvcName} does not exist")
@@ -529,4 +564,4 @@ def launchAiServiceUpgradePipeline(dynClient: DynamicClient,
529564
pipelineRunsAPI.apply(body=pipelineRun, namespace=namespace)
530565

531566
pipelineURL = f"{getConsoleURL(dynClient)}/k8s/ns/aiservice-{aiserviceInstanceId}-pipelines/tekton.dev~v1beta1~PipelineRun/{aiserviceInstanceId}-upgrade-{timestamp}"
532-
return pipelineURL
567+
return pipelineURL

0 commit comments

Comments
 (0)