Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
110a0f1
[patch] Initial draft of the new upgrade pipeline tasks with Manage F…
Apr 10, 2025
6a5663f
[patch] Including workspaces and parameters from the install pipeline.
Apr 11, 2025
bf6e8fb
[patch] Removing duplicate params.
Apr 11, 2025
eec0ccd
[patch] Adding Manage-specific pipeline params.
Apr 14, 2025
881446e
[patch] Forgot to push one file.
Apr 14, 2025
6b5edb6
[patch] Formatting.
Apr 14, 2025
f634cf3
[patch] Adding shared-configs and shared-pod-templates to the upgrade…
Apr 14, 2025
5326c91
[patch] Adding dev mode properties.
Apr 14, 2025
2b0329b
[patch] Disabling the manage-upgrade task for now, to test if the Man…
Apr 15, 2025
5f3d268
[patch] Testing with "{{ false }}" instead of literal false.
Apr 15, 2025
3ffe19e
[patch] Fixing the when clause.
Apr 15, 2025
a068418
[patch] mas_workspace_id param is needed when installing Manage Found…
Apr 15, 2025
4f65c12
[patch] Checking if Manage is installed during the upgrade to 9.0 to …
Apr 16, 2025
3702f71
[patch] Passing mas_workspace_id to pipelinerun-upgrade.yml.j2
Apr 16, 2025
713a8ae
[patch] Ignoring silentMode for s390x architecture as it requires int…
Apr 16, 2025
b65602c
[patch] Adding when conditions to all upgrade tasks that are responsi…
Apr 16, 2025
2c7288a
[patch] Passing masChannel to launchUpgradePipeline. Allowing the nex…
Apr 16, 2025
2c9c7de
[patch] Moving the prompts for entitlement key and artifactory creden…
Apr 16, 2025
4560d9a
[patch] Removing the changes to manually set nextChannel and and pass…
Apr 17, 2025
46c6130
[patch] Adding back the possibility to manually set nextChannel in de…
Apr 17, 2025
d01bda4
Merge branch 'master' of https://github.com/ibm-mas/cli into issue-MA…
Apr 17, 2025
b5f9963
[patch] Updating python-devops to the latest.
Apr 17, 2025
3dc7ce7
[patch] The template syntax did not work for some reason, trying to a…
Apr 17, 2025
c6243d0
[patch] Using a different approach to make sure the new entry to the …
Apr 17, 2025
e5c4875
[patch] Removing a print and using ansible-devops with a small change…
Apr 22, 2025
c421a47
[patch] Reverting the last change in ansible-devops
Apr 22, 2025
e8e5544
[patch] installIoT needs to be set to false because, if IoT is alread…
Apr 23, 2025
e54d7dc
Merge branch 'master' of https://github.com/ibm-mas/cli into issue-MA…
Apr 24, 2025
c90f6da
[patch] Reverting the changes in python-devops and ansible-devops to …
Apr 24, 2025
e8854e9
[patch] Making sure settings.aio.install is set to false when install…
Apr 28, 2025
7632aea
[patch] Re-adding 9.1.x-dev channels in python-devops and ansible-dev…
Apr 28, 2025
15b1793
[patch] Do not run configDb2 in silent mode during install, only duri…
Apr 29, 2025
6736e0a
Merge branch 'master' of https://github.com/ibm-mas/cli into issue-MA…
Apr 29, 2025
3fbbae1
[patch] Updating python-devops
Apr 29, 2025
f2b6445
[patch] Removing ansible-devops and python-devops tar.gz files.
Apr 29, 2025
8d32b80
Merge branch 'master' into issue-MASCORE-6276
blechner May 2, 2025
0195169
Merge branch 'master' into issue-MASCORE-6276
blechner May 5, 2025
95862f0
Merge branch 'master' into issue-MASCORE-6276
blechner May 5, 2025
5692172
Merge branch 'master' into issue-MASCORE-6276
blechner May 6, 2025
001426c
Merge branch 'master' into issue-MASCORE-6276
alequint May 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions python/src/mas/cli/install/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ def configApps(self):
self.installManage = True
self.isManageFoundation = True
self.setParam("is_full_manage", "false")
self.setParam("mas_app_settings_aio_flag", "false")
self.manageAppName = "Manage foundation"
self.printDescription([f"{self.manageAppName} installs the following capabilities: User, Security groups, Application configurator and Mobile configurator."])
else:
Expand Down
79 changes: 50 additions & 29 deletions python/src/mas/cli/install/settings/db2Settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,26 @@


class Db2SettingsMixin():
def configDb2(self) -> None:
self.printH1("Configure Databases")
# In silentMode, no prompts will show up for "happy path" DB2 configuration scenarios. Prompts will still show up when an input is absolutely required
# Settings under showAdvancedOptions are always prompted
def configDb2(self, silentMode=False) -> None:
if not silentMode:
self.printH1("Configure Databases")
# The channel used for Db2 used has not changed since the January 2024 catalog update
self.params["db2_channel"] = "v110509.0"

# If neither Iot or Manage is being installed, we have nothing to do
if not self.installIoT and not self.installManage:
print_formatted_text("No applications have been selected that require a Db2 installation")
self.setParam("db2_action_system", "none")
self.setParam("db2_action_manage", "none")
if not silentMode:
print_formatted_text("No applications have been selected that require a Db2 installation")
self.setParam("db2_action_system", "none")
self.setParam("db2_action_manage", "none")
return

# For now we are limiting users to bring your own database for Manage on s390x
# Eventually we will be able to remove this clause and allow the standard logic to work for both s390x and amd64
if self.architecture == "s390x" and self.installManage:
# silentMode does not apply for s390x because it requires interaction when selecting local config directory
self.printDescription([
"Installation of a Db2 instance using the IBM Db2 Universal Operator is not currently supported on s390x, please provide configuration details for the database you wish to use.",
])
Expand All @@ -51,21 +56,26 @@ def configDb2(self) -> None:

# Proceed as normal
# We know we are installing either IoT or Manage, and on amd64 target architecture
self.printDescription([
f"The installer can setup one or more IBM Db2 instances in your OpenShift cluster for the use of applications that require a JDBC datasource (IoT, {self.manageAppName}, Monitor, & Predict) or you may choose to configure MAS to use an existing database"
])
if not silentMode:
self.printDescription([
f"The installer can setup one or more IBM Db2 instances in your OpenShift cluster for the use of applications that require a JDBC datasource (IoT, {self.manageAppName}, Monitor, & Predict) or you may choose to configure MAS to use an existing database"
])

self.setDB2DefaultSettings()

instanceId = self.getParam('mas_instance_id')
# Do we need to set up an IoT database?
if self.installIoT:
self.printH2("Database Configuration for Maximo IoT")
self.printDescription([
"Maximo IoT requires a shared system-scope Db2 instance because others application in the suite require access to the same database source",
" - Only IBM Db2 is supported for this database"
])
if self.yesOrNo("Create system Db2 instance using the IBM Db2 Universal Operator"):
if not silentMode:
self.printH2("Database Configuration for Maximo IoT")
self.printDescription([
"Maximo IoT requires a shared system-scope Db2 instance because others application in the suite require access to the same database source",
" - Only IBM Db2 is supported for this database"
])
createSystemDb2UsingUniversalOperator = True
if not silentMode:
createSystemDb2UsingUniversalOperator = self.yesOrNo("Create system Db2 instance using the IBM Db2 Universal Operator")
if createSystemDb2UsingUniversalOperator:
self.setParam("db2_action_system", "install")
else:
self.setParam("db2_action_system", "byo")
Expand All @@ -85,28 +95,39 @@ def configDb2(self) -> None:
self.setParam("db2_action_system", "none")

if self.installManage:
self.printH2(f"Database Configuration for Maximo {self.manageAppName}")
self.printDescription([
f"Maximo {self.manageAppName} can be configured to share the system Db2 instance or use it's own dedicated database:",
" - Use of a shared instance has a significant footprint reduction but is only recommended for development/test/demo installs",
" - In most production systems you will want to use a dedicated database",
" - IBM Db2, Oracle Database, & Microsoft SQL Server are all supported database options"
])
if not silentMode:
self.printH2(f"Database Configuration for Maximo {self.manageAppName}")
self.printDescription([
f"Maximo {self.manageAppName} can be configured to share the system Db2 instance or use it's own dedicated database:",
" - Use of a shared instance has a significant footprint reduction but is only recommended for development/test/demo installs",
" - In most production systems you will want to use a dedicated database",
" - IBM Db2, Oracle Database, & Microsoft SQL Server are all supported database options"
])
# Determine whether to use the system or a dedicated database
if self.installIoT and self.yesOrNo(f"Re-use System Db2 instance for {self.manageAppName} application"):
reuseSystemDb2 = False
if self.installIoT:
if not silentMode:
reuseSystemDb2 = self.yesOrNo(f"Re-use System Db2 instance for {self.manageAppName} application")
if reuseSystemDb2:
# We are going to bind Manage to the system database, which has already been set up in the previous step
self.setParam("mas_appws_bindings_jdbc_manage", "system")
self.setParam("db2_action_manage", "none")
else:
self.setParam("mas_appws_bindings_jdbc_manage", "workspace-application")
if self.yesOrNo(f"Create {self.manageAppName} dedicated Db2 instance using the IBM Db2 Universal Operator"):
createSystemDb2UsingUniversalOperator = True
if not silentMode:
createSystemDb2UsingUniversalOperator = self.yesOrNo(f"Create {self.manageAppName} dedicated Db2 instance using the IBM Db2 Universal Operator")
if createSystemDb2UsingUniversalOperator:
self.setParam("db2_action_manage", "install")
self.printDescription([
f"Available Db2 instance types for {self.manageAppName}:",
" 1. DB2 Warehouse (Default option)",
" 2. DB2 Online Transactional Processing (OLTP)"
])
self.promptForListSelect(message=f"Select the {self.manageAppName} dedicated DB2 instance type", options=["db2wh", "db2oltp"], param="db2_type", default="1")
if not silentMode:
self.printDescription([
f"Available Db2 instance types for {self.manageAppName}:",
" 1. DB2 Warehouse (Default option)",
" 2. DB2 Online Transactional Processing (OLTP)"
])
self.promptForListSelect(message=f"Select the {self.manageAppName} dedicated DB2 instance type", options=["db2wh", "db2oltp"], param="db2_type", default="1")
else:
self.setParam("db2_type", "db2wh")
else:
workspaceId = self.getParam("mas_workspace_id")
self.setParam("db2_action_manage", "byo")
Expand Down
49 changes: 41 additions & 8 deletions python/src/mas/cli/upgrade/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@
from ..cli import BaseApp
from ..validators import InstanceIDValidator
from .argParser import upgradeArgParser
from .settings import UpgradeSettingsMixin

from mas.devops.ocp import createNamespace
from mas.devops.mas import listMasInstances, getMasChannel
from mas.devops.mas import listMasInstances, getMasChannel, getWorkspaceId, verifyAppInstance
from mas.devops.tekton import installOpenShiftPipelines, updateTektonDefinitions, launchUpgradePipeline

logger = logging.getLogger(__name__)


class UpgradeApp(BaseApp):
class UpgradeApp(BaseApp, UpgradeSettingsMixin):
def upgrade(self, argv):
"""
Upgrade MAS instance
Expand All @@ -38,13 +39,16 @@ def upgrade(self, argv):
self.noConfirm = args.no_confirm
self.skipPreCheck = args.skip_pre_check
self.licenseAccepted = args.accept_license
self.devMode = args.dev_mode

if instanceId is None:
self.printH1("Set Target OpenShift Cluster")
# Connect to the target cluster
self.connect()
else:
logger.debug("MAS instance ID is set, so we assume already connected to the desired OCP")
# Need to lookup target architecture because configDb2 will try to access self.architecture
self.lookupTargetArchitecture()

if self.dynamicClient is None:
print_formatted_text(HTML("<Red>Error: The Kubernetes dynamic Client is not available. See log file for details</Red>"))
Expand All @@ -71,16 +75,21 @@ def upgrade(self, argv):

currentChannel = getMasChannel(self.dynamicClient, instanceId)
if currentChannel is not None:
if currentChannel not in self.upgrade_path:
self.fatalError(f"No upgrade available, {instanceId} is are already on the latest release {currentChannel}")
nextChannel = self.upgrade_path[currentChannel]
if self.devMode:
# This is mainly used for the scenario where Manage Foundation would be installed, because core-upgrade does not use the value of nextChannel,
# it uses a compatibility_matrix object in ansible-devops to determine the next channel, so nextChannel is only informative for core upgrade purposes
nextChannel = prompt(HTML('<Yellow>Custom channel</Yellow> '))
else:
if currentChannel not in self.upgrade_path:
self.fatalError(f"No upgrade available, {instanceId} is are already on the latest release {currentChannel}")
nextChannel = self.upgrade_path[currentChannel]
else:
# We still allow the upgrade to proceed even though we can't detect the MAS instance. The upgrade may be being
# queued up to run after install for instance
currentChannel = "Unknown"
nextChannel = "Unknown"

if not self.licenseAccepted:
if not self.licenseAccepted and not self.devMode:
self.printH1("License Terms")
self.printDescription([
"To continue with the upgrade, you must accept the license terms:",
Expand All @@ -93,6 +102,30 @@ def upgrade(self, argv):
if not self.yesOrNo("Do you accept the license terms"):
exit(1)

# The only scenario where Manage Foundation needs to be installed during an upgrade is from 9.0.x to 9.1.x (if Manage was not already installed in 9.0.x).
self.setParam("should_install_manage_foundation", "false")
if nextChannel.startswith("9.1") and not verifyAppInstance(self.dynamicClient, instanceId, "manage"):
self.manageAppName = "Manage foundation"
self.showAdvancedOptions = False
self.installIoT = False
self.installManage = True
self.isManageFoundation = True
self.printDescription([f"{self.manageAppName} installs the following capabilities: User, Security groups, Application configurator and Mobile configurator."])
self.printH1("Configure IBM Container Registry")
self.promptForString("IBM entitlement key", "ibm_entitlement_key", isPassword=True)
if self.devMode:
self.promptForString("Artifactory username", "artifactory_username")
self.promptForString("Artifactory token", "artifactory_token", isPassword=True)
self.setParam("should_install_manage_foundation", "true")
self.setParam("is_full_manage", "false")
self.setParam("mas_appws_components", "")
self.setParam("mas_app_settings_aio_flag", "false")
self.setParam("mas_app_channel_manage", nextChannel)
self.setParam("mas_workspace_id", getWorkspaceId(self.dynamicClient, instanceId))
# It has been decided that we don't need to ask for any specific Manage Settings
# self.manageSettings()
self.configDb2(silentMode=True)

self.printH1("Review Settings")
print_formatted_text(HTML(f"<LightSlateGrey>Instance ID ..................... {instanceId}</LightSlateGrey>"))
print_formatted_text(HTML(f"<LightSlateGrey>Current MAS Channel ............. {currentChannel}</LightSlateGrey>"))
Expand All @@ -101,7 +134,7 @@ def upgrade(self, argv):

if not self.noConfirm:
print()
continueWithUpgrade = self.yesOrNo("Proceed with these settings?")
continueWithUpgrade = self.yesOrNo("Proceed with these settings")

if self.noConfirm or continueWithUpgrade:
self.createTektonFileWithDigest()
Expand All @@ -122,7 +155,7 @@ def upgrade(self, argv):
h.stop_and_persist(symbol=self.successIcon, text=f"Latest Tekton definitions are installed (v{self.version})")

with Halo(text='Submitting PipelineRun for {instanceId} upgrade', spinner=self.spinner) as h:
pipelineURL = launchUpgradePipeline(self.dynamicClient, instanceId, self.skipPreCheck)
pipelineURL = launchUpgradePipeline(self.dynamicClient, instanceId, self.skipPreCheck, params=self.params)
if pipelineURL is not None:
h.stop_and_persist(symbol=self.successIcon, text=f"PipelineRun for {instanceId} upgrade submitted")
print_formatted_text(HTML(f"\nView progress:\n <Cyan><u>{pipelineURL}</u></Cyan>\n"))
Expand Down
7 changes: 7 additions & 0 deletions python/src/mas/cli/upgrade/argParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@
default=False,
help="Accept all license terms without prompting"
)
otherArgGroup.add_argument(
"--dev-mode",
required=False,
action="store_true",
default=False,
help="Configure upgrade for development mode",
)
otherArgGroup.add_argument(
'-h', "--help",
action='help',
Expand Down
19 changes: 19 additions & 0 deletions python/src/mas/cli/upgrade/settings/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# *****************************************************************************
# Copyright (c) 2025 IBM Corporation and other Contributors.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# *****************************************************************************

from ...install.settings.db2Settings import Db2SettingsMixin
from ...install.settings.manageSettings import ManageSettingsMixin


class UpgradeSettingsMixin(Db2SettingsMixin, ManageSettingsMixin):
"""
This class collects all the Mixins providing interactive prompts for mas-upgrade
"""
pass
Loading