Skip to content

Commit 86d7ebd

Browse files
committed
Update with new pipelinerun for mas-backup
1 parent 432a08d commit 86d7ebd

File tree

3 files changed

+174
-5
lines changed

3 files changed

+174
-5
lines changed

src/mas/devops/tekton.py

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def updateTektonDefinitions(namespace: str, yamlFile: str) -> None:
262262
logger.debug(line)
263263

264264

265-
def preparePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None, storageClass: str = None, accessMode: str = None, waitForBind: bool = True, configureRBAC: bool = True):
265+
def preparePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None, storageClass: str = None, accessMode: str = None, waitForBind: bool = True, configureRBAC: bool = True, createBackupPVC: bool = False, backupStorageSize: str = "20Gi"):
266266
"""
267267
Prepare a namespace for MAS pipelines by creating RBAC and PVC resources.
268268
@@ -276,6 +276,8 @@ def preparePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None,
276276
accessMode (str, optional): Access mode for the PVC. Defaults to None.
277277
waitForBind (bool, optional): Whether to wait for PVC to bind. Defaults to True.
278278
configureRBAC (bool, optional): Whether to configure RBAC. Defaults to True.
279+
createBackupPVC (bool, optional): Whether to create backup PVC. Defaults to False.
280+
backupStorageSize (str, optional): Size of the backup PVC storage. Defaults to "20Gi".
279281
280282
Returns:
281283
None
@@ -304,6 +306,9 @@ def preparePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None,
304306

305307
# Create PVC (instanceId namespace only)
306308
if instanceId is not None:
309+
pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim")
310+
311+
# Create config PVC
307312
template = env.get_template("pipelines-pvc.yml.j2")
308313
renderedTemplate = template.render(
309314
mas_instance_id=instanceId,
@@ -312,24 +317,51 @@ def preparePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None,
312317
)
313318
logger.debug(renderedTemplate)
314319
pvc = yaml.safe_load(renderedTemplate)
315-
pvcAPI = dynClient.resources.get(api_version="v1", kind="PersistentVolumeClaim")
316320
pvcAPI.apply(body=pvc, namespace=namespace)
321+
317322
# Automatically determine if we should wait for PVC binding based on storage class
318323
volumeBindingMode = getStorageClassVolumeBindingMode(dynClient, storageClass)
319324
waitForBind = (volumeBindingMode == "Immediate")
320325
if waitForBind:
321-
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, waiting for PVC to bind")
326+
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, waiting for config PVC to bind")
322327
pvcIsBound = False
323328
while not pvcIsBound:
324329
configPVC = pvcAPI.get(name="config-pvc", namespace=namespace)
325330
if configPVC.status.phase == "Bound":
326331
pvcIsBound = True
327332
else:
328-
logger.debug("Waiting 15s before checking status of PVC again")
333+
logger.debug("Waiting 15s before checking status of config PVC again")
329334
logger.debug(configPVC)
330335
sleep(15)
331336
else:
332-
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, skipping PVC bind wait")
337+
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, skipping config PVC bind wait")
338+
339+
# Create backup PVC if requested
340+
if createBackupPVC:
341+
logger.info("Creating backup PVC")
342+
backupTemplate = env.get_template("pipelines-backup-pvc.yml.j2")
343+
renderedBackupTemplate = backupTemplate.render(
344+
mas_instance_id=instanceId,
345+
pipeline_storage_class=storageClass,
346+
pipeline_storage_accessmode=accessMode
347+
)
348+
logger.debug(renderedBackupTemplate)
349+
backupPvc = yaml.safe_load(renderedBackupTemplate)
350+
pvcAPI.apply(body=backupPvc, namespace=namespace)
351+
352+
if waitForBind:
353+
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, waiting for backup PVC to bind")
354+
backupPvcIsBound = False
355+
while not backupPvcIsBound:
356+
backupPVC = pvcAPI.get(name="backup-pvc", namespace=namespace)
357+
if backupPVC.status.phase == "Bound":
358+
backupPvcIsBound = True
359+
else:
360+
logger.debug("Waiting 15s before checking status of backup PVC again")
361+
logger.debug(backupPVC)
362+
sleep(15)
363+
else:
364+
logger.info(f"Storage class {storageClass} uses volumeBindingMode={volumeBindingMode}, skipping backup PVC bind wait")
333365

334366

335367
def prepareAiServicePipelinesNamespace(dynClient: DynamicClient, instanceId: str = None, storageClass: str = None, accessMode: str = None, waitForBind: bool = True, configureRBAC: bool = True):
@@ -697,6 +729,28 @@ def launchUpdatePipeline(dynClient: DynamicClient, params: dict) -> str:
697729
return pipelineURL
698730

699731

732+
def launchBackupPipeline(dynClient: DynamicClient, params: dict) -> str:
733+
"""
734+
Create a PipelineRun to backup a MAS instance.
735+
736+
Parameters:
737+
dynClient (DynamicClient): OpenShift Dynamic Client
738+
params (dict): Backup parameters including instance ID and configuration
739+
740+
Returns:
741+
str: URL to the PipelineRun in the OpenShift console
742+
743+
Raises:
744+
NotFoundError: If resources cannot be created
745+
"""
746+
instanceId = params["mas_instance_id"]
747+
namespace = f"mas-{instanceId}-pipelines"
748+
timestamp = launchPipelineRun(dynClient, namespace, "pipelinerun-backup", params)
749+
750+
pipelineURL = f"{getConsoleURL(dynClient)}/k8s/ns/mas-{instanceId}-pipelines/tekton.dev~v1beta1~PipelineRun/{instanceId}-backup-{timestamp}"
751+
return pipelineURL
752+
753+
700754
def launchAiServiceUpgradePipeline(dynClient: DynamicClient,
701755
aiserviceInstanceId: str,
702756
skipPreCheck: bool = False,
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
apiVersion: tekton.dev/v1beta1
3+
kind: PipelineRun
4+
metadata:
5+
generateName: {{ mas_instance_id }}-backup-{{ backup_version }}-
6+
labels:
7+
mas.ibm.com/instanceId: "{{ mas_instance_id }}"
8+
spec:
9+
pipelineRef:
10+
name: mas-backup
11+
serviceAccountName: pipeline
12+
workspaces:
13+
- name: shared-configs
14+
persistentVolumeClaim:
15+
claimName: config-pvc
16+
- name: shared-backups
17+
persistentVolumeClaim:
18+
claimName: backup-pvc
19+
params:
20+
# Common Parameters
21+
- name: image_pull_policy
22+
value: IfNotPresent
23+
- name: mas_instance_id
24+
value: "{{ mas_instance_id }}"
25+
26+
# Backup Configuration
27+
- name: backup_version
28+
value: "{{ backup_version }}"
29+
30+
# Component Flags
31+
{% if include_sls is defined and include_sls != "" %}
32+
- name: include_sls
33+
value: "{{ include_sls }}"
34+
{% endif %}
35+
36+
# MongoDB Configuration
37+
{% if mongodb_namespace is defined and mongodb_namespace != "" %}
38+
- name: mongodb_namespace
39+
value: "{{ mongodb_namespace }}"
40+
{% endif %}
41+
{% if mongodb_instance_name is defined and mongodb_instance_name != "" %}
42+
- name: mongodb_instance_name
43+
value: "{{ mongodb_instance_name }}"
44+
{% endif %}
45+
{% if mongodb_provider is defined and mongodb_provider != "" %}
46+
- name: mongodb_provider
47+
value: "{{ mongodb_provider }}"
48+
{% endif %}
49+
50+
# SLS Configuration
51+
{% if sls_namespace is defined and sls_namespace != "" %}
52+
- name: sls_namespace
53+
value: "{{ sls_namespace }}"
54+
{% endif %}
55+
56+
# Certificate Manager Configuration
57+
{% if cert_manager_provider is defined and cert_manager_provider != "" %}
58+
- name: cert_manager_provider
59+
value: "{{ cert_manager_provider }}"
60+
{% endif %}
61+
62+
# Development Build Support
63+
{% if artifactory_username is defined and artifactory_username != "" %}
64+
- name: artifactory_username
65+
value: "{{ artifactory_username }}"
66+
{% endif %}
67+
{% if artifactory_token is defined and artifactory_token != "" %}
68+
- name: artifactory_token
69+
value: "{{ artifactory_token }}"
70+
{% endif %}
71+
72+
# Upload Configuration
73+
{% if upload_backup is defined and upload_backup != "" %}
74+
- name: upload_backup
75+
value: "{{ upload_backup }}"
76+
{% endif %}
77+
{% if aws_access_key_id is defined and aws_access_key_id != "" %}
78+
- name: aws_access_key_id
79+
value: "{{ aws_access_key_id }}"
80+
{% endif %}
81+
{% if aws_secret_access_key is defined and aws_secret_access_key != "" %}
82+
- name: aws_secret_access_key
83+
value: "{{ aws_secret_access_key }}"
84+
{% endif %}
85+
{% if s3_bucket_name is defined and s3_bucket_name != "" %}
86+
- name: s3_bucket_name
87+
value: "{{ s3_bucket_name }}"
88+
{% endif %}
89+
{% if s3_region is defined and s3_region != "" %}
90+
- name: s3_region
91+
value: "{{ s3_region }}"
92+
{% endif %}
93+
{% if artifactory_url is defined and artifactory_url != "" %}
94+
- name: artifactory_url
95+
value: "{{ artifactory_url }}"
96+
{% endif %}
97+
{% if artifactory_repository is defined and artifactory_repository != "" %}
98+
- name: artifactory_repository
99+
value: "{{ artifactory_repository }}"
100+
{% endif %}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
# PVC for backup storage
3+
apiVersion: v1
4+
kind: PersistentVolumeClaim
5+
metadata:
6+
name: backup-pvc
7+
namespace: mas-{{ mas_instance_id }}-pipelines
8+
spec:
9+
accessModes:
10+
- {{ pipeline_storage_accessmode }}
11+
volumeMode: Filesystem
12+
storageClassName: {{ pipeline_storage_class }}
13+
resources:
14+
requests:
15+
storage: {{ backup_storage_size }}

0 commit comments

Comments
 (0)