diff --git a/.secrets.baseline b/.secrets.baseline index f7e0ae995f2..124a2a24437 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2025-08-15T21:40:03Z", + "generated_at": "2025-09-03T13:58:29Z", "plugins_used": [ { "name": "AWSKeyDetector" diff --git a/Makefile b/Makefile index 36fb6d3319f..15dbc5c3100 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ tekton-test: tekton docker: docker build -t quay.io/ibmmas/cli:100.0.0-pre.local image/cli -all: ansible python tekton docker +all: ansible-devops python tekton docker run: docker run -ti quay.io/ibmmas/cli:100.0.0-pre.local diff --git a/python/src/mas/cli/update/app.py b/python/src/mas/cli/update/app.py index 1c3ec1df3a4..5b2b795c9f5 100644 --- a/python/src/mas/cli/update/app.py +++ b/python/src/mas/cli/update/app.py @@ -11,6 +11,7 @@ import logging import logging.handlers +from typing import Callable from halo import Halo from prompt_toolkit import print_formatted_text, HTML @@ -21,7 +22,7 @@ from .argParser import updateArgParser from mas.devops.ocp import createNamespace, getStorageClasses, getConsoleURL -from mas.devops.mas import listMasInstances, getCurrentCatalog +from mas.devops.mas import listMasInstances, listAiServiceInstances, getCurrentCatalog from mas.devops.tekton import preparePipelinesNamespace, installOpenShiftPipelines, updateTektonDefinitions, launchUpdatePipeline @@ -94,7 +95,10 @@ def update(self, argv): # deprecated MaximoApplicationSuite ImageContentSourcePolicy instead of the new ImageDigestMirrorSet self.isAirgap() self.reviewCurrentCatalog() - self.reviewMASInstance() + isMasInstalled = self.reviewMASInstance() + isAiServiceInstalled = self.reviewAiServiceInstance() + if not isMasInstalled and not isAiServiceInstalled: + self.fatalError(["No MAS or AI Service instances were detected on the cluster => nothing to update! See log file for details"]) if self.args.mas_catalog_version is None: # Interactive mode @@ -228,15 +232,23 @@ def reviewCurrentCatalog(self) -> None: f" {catalogInfo['image']}" ]) - def reviewMASInstance(self) -> None: - self.printH1("Review MAS Instances") - self.printDescription(["The following MAS intances are installed on the target cluster and will be affected by the catalog update:"]) + 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') + + def reviewInstances(self, getInstances: Callable, name: str, kind: str) -> bool: + self.printH1(f"Review {name} Instances") try: - suites = listMasInstances(self.dynamicClient) - for suite in suites: - self.printDescription([f"- {suite['metadata']['name']} v{suite['status']['versions']['reconciled']}"]) + instances = getInstances(self.dynamicClient) + 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: - self.fatalError("No MAS instances were detected on the cluster (Suite.core.mas.ibm.com/v1 API is not available). See log file for details") + self.printDescription([f"No {name} instances were detected on the cluster ({kind} API is not available)"]) + return False def chooseCatalog(self) -> None: self.printH1("Select IBM Maximo Operator Catalog Version")