diff --git a/python/src/mas/cli/update/app.py b/python/src/mas/cli/update/app.py index 9e7a6874dc8..fdedb98a10e 100644 --- a/python/src/mas/cli/update/app.py +++ b/python/src/mas/cli/update/app.py @@ -233,17 +233,32 @@ def reviewMASInstance(self) -> bool: return self.reviewInstances(listMasInstances, 'MAS', 'Suite.core.mas.ibm.com/v1') def reviewAiServiceInstance(self) -> bool: - return self.reviewInstances(listAiServiceInstances, 'AI Service', 'AIServiceApp.aiservice.ibm.com/v1') + return self.reviewInstances(listAiServiceInstances, 'AI Service', 'AIServiceApp.aiservice.ibm.com/v1', "aiservice_instance_ids") - def reviewInstances(self, getInstances: Callable, name: str, kind: str) -> bool: + def reviewInstances(self, getInstances: Callable, name: str, kind: str, instanceParamKey: str = "") -> bool: self.printH1(f"Review {name} Instances") try: instances = getInstances(self.dynamicClient) + + if len(instances) == 0: + if instanceParamKey != "": + self.setParam(instanceParamKey, "") + self.printDescription([f"No {name} instances were detected on the cluster"]) + return False + + if instanceParamKey != "": + self.setParam(instanceParamKey, "") + for instance in instances: + param = self.getParam(instanceParamKey) + self.setParam(instanceParamKey, f"{param},{instance['metadata']['name']}".lstrip(",")) + self.printDescription([f"The following {name} instances are installed on the target cluster and will be affected by the catalog update:"]) for instance in instances: self.printDescription([f"- {instance['metadata']['name']} v{instance['status']['versions']['reconciled']}"]) return True except ResourceNotFoundError: + if instanceParamKey != "": + self.setParam(instanceParamKey, "") self.printDescription([f"No {name} instances were detected on the cluster ({kind} API is not available)"]) return False diff --git a/tekton/generate-tekton-tasks.yml b/tekton/generate-tekton-tasks.yml index 3518e1ce5e8..b180b7f3cd6 100644 --- a/tekton/generate-tekton-tasks.yml +++ b/tekton/generate-tekton-tasks.yml @@ -54,6 +54,7 @@ - odh - rhoai - aiservice-upgrade + - aiservice-migration # 4. Generate Tasks (FVT) # ------------------------------------------------------------------------- diff --git a/tekton/src/pipelines/mas-update.yml.j2 b/tekton/src/pipelines/mas-update.yml.j2 index a54c077e398..95b219a0395 100644 --- a/tekton/src/pipelines/mas-update.yml.j2 +++ b/tekton/src/pipelines/mas-update.yml.j2 @@ -152,6 +152,13 @@ spec: type: string default: "" description: ReadWriteMany storage class + + # AI Service + # ------------------------------------------------------------------------- + - name: aiservice_instance_ids + type: string + default: "" + description: Comma-separated list of AI Service instance IDs tasks: # 1. Wait for approval & verify health of the cluster before we change anything @@ -337,8 +344,22 @@ spec: runAfter: - update-cp4d + # 6. Migrate any AI Service instances. Updating to a new feature channel release + # could require migration as release 9.2 introduces a significant architectural change. + # AI Service migration + # ------------------------------------------------------------------------- + - name: aiservice-migration + timeout: "0" + taskRef: + kind: Task + name: mas-devops-aiservice-migration + runAfter: + - post-update-verify + params: + - name: aiservice_instance_ids + value: $(params.aiservice_instance_ids) - # 6. Verify health of the cluster after dependencies updates + # 7. Verify health of the cluster after dependencies updates # ------------------------------------------------------------------------- {{ lookup('template', 'taskdefs/cluster-setup/ocp-verify-all.yml.j2', template_vars={ 'name': 'post-deps-update-verify', diff --git a/tekton/src/tasks/aiservice/aiservice-migration.yml.j2 b/tekton/src/tasks/aiservice/aiservice-migration.yml.j2 new file mode 100644 index 00000000000..f2f0ebbbff9 --- /dev/null +++ b/tekton/src/tasks/aiservice/aiservice-migration.yml.j2 @@ -0,0 +1,45 @@ +--- +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mas-devops-aiservice-migration +spec: + params: + {{ lookup('template', task_src_dir ~ '/common/cli-params.yml.j2') | indent(4) }} + + - name: aiservice_instance_ids + type: string + default: "" + description: Comma-separated AI Service instance IDs + + stepTemplate: + env: + {{ lookup('template', task_src_dir ~ '/common/cli-env.yml.j2') | indent(6) }} + + steps: + - name: aiservice-migration + image: quay.io/ibmmas/cli:latest + imagePullPolicy: $(params.image_pull_policy) + script: | + #!/usr/bin/env bash + set -euo pipefail + + INSTANCE_IDS='$(params.aiservice_instance_ids)' + + if [ -z "${INSTANCE_IDS}" ]; then + echo "No AI Service instances detected, skipping migration" + exit 0 + fi + + IFS=',' read -ra IDS <<< "${INSTANCE_IDS}" + + for id in "${IDS[@]}"; do + id="$(echo "$id" | xargs)" + if [ -z "$id" ]; then + continue + fi + + echo "Running AI Service migration for instance: $id" + export AISERVICE_INSTANCE_ID="$id" + /opt/app-root/src/run-role.sh aiservice_migration + done