mas-cli 11.4.0__py3-none-any.whl → 11.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mas-cli might be problematic. Click here for more details.

mas/cli/__init__.py CHANGED
@@ -8,4 +8,4 @@
8
8
  #
9
9
  # *****************************************************************************
10
10
 
11
- __version__ = "11.4.0" # Python module compatible semver
11
+ __version__ = "11.6.0" # Python module compatible semver
mas/cli/cli.py CHANGED
@@ -30,7 +30,6 @@ from prompt_toolkit import prompt, print_formatted_text, HTML
30
30
  from mas.devops.mas import isAirgapInstall
31
31
  from mas.devops.ocp import connect, isSNO
32
32
 
33
- from .validators import YesNoValidator
34
33
  from .displayMixins import PrintMixin, PromptMixin
35
34
 
36
35
  # Configure the logger
@@ -97,7 +96,7 @@ class BaseApp(PrintMixin, PromptMixin):
97
96
 
98
97
  # Set up a log handler (5mb rotating log file)
99
98
  ch = logging.handlers.RotatingFileHandler(
100
- "mas.log", maxBytes=(1048576*5), backupCount=2
99
+ "mas.log", maxBytes=(1048576 * 5), backupCount=2
101
100
  )
102
101
  ch.setLevel(logging.DEBUG)
103
102
  ch.setFormatter(chFormatter)
@@ -108,7 +107,7 @@ class BaseApp(PrintMixin, PromptMixin):
108
107
  rootLogger.setLevel(logging.DEBUG)
109
108
 
110
109
  # Supports extended semver, unlike mas.cli.__version__
111
- self.version = "11.4.0"
110
+ self.version = "11.6.0"
112
111
  self.h1count = 0
113
112
  self.h2count = 0
114
113
 
@@ -138,7 +137,8 @@ class BaseApp(PrintMixin, PromptMixin):
138
137
  "monitor": ["9.0.x", "8.11.x"],
139
138
  "optimizer": ["9.0.x", "8.5.x"],
140
139
  "predict": ["9.0.x", "8.9.x"],
141
- "visualinspection": ["9.0.x", "8.9.x"]
140
+ "visualinspection": ["9.0.x", "8.9.x"],
141
+ "aibroker": ["9.0.x"]
142
142
  },
143
143
  "8.11.x": {
144
144
  "assist": ["8.8.x", "8.7.x"],
@@ -223,7 +223,7 @@ class BaseApp(PrintMixin, PromptMixin):
223
223
  else:
224
224
  return []
225
225
 
226
- def fatalError(self, message: str, exception: Exception=None) -> None:
226
+ def fatalError(self, message: str, exception: Exception = None) -> None:
227
227
  if exception is not None:
228
228
  logger.error(message)
229
229
  logger.exception(exception, stack_info=True)
@@ -289,8 +289,7 @@ class BaseApp(PrintMixin, PromptMixin):
289
289
  print()
290
290
  if not self.noConfirm:
291
291
  # We are already connected to a cluster, but prompt the user if they want to use this connection
292
- continueWithExistingCluster = prompt(HTML('<Yellow>Proceed with this cluster?</Yellow> '), validator=YesNoValidator(), validate_while_typing=False)
293
- promptForNewServer = continueWithExistingCluster in ["n", "no"]
292
+ promptForNewServer = not self.yesOrNo("Proceed with this cluster?")
294
293
  except Exception as e:
295
294
  # We are already connected to a cluster, but the connection is not valid so prompt for connection details
296
295
  logger.debug("Failed looking up OpenShift Console route to verify connection")
@@ -311,7 +310,7 @@ class BaseApp(PrintMixin, PromptMixin):
311
310
  print_formatted_text(HTML("<Red>Unable to connect to cluster. See log file for details</Red>"))
312
311
  exit(1)
313
312
 
314
- def initializeApprovalConfigMap(self, namespace: str, id: str, key: str=None, maxRetries: int=100, delay: int=300, ignoreFailure: bool=True) -> None:
313
+ def initializeApprovalConfigMap(self, namespace: str, id: str, key: str = None, maxRetries: int = 100, delay: int = 300, ignoreFailure: bool = True) -> None:
315
314
  """
316
315
  Set key = None if you don't want approval workflow enabled
317
316
  """
mas/cli/displayMixins.py CHANGED
@@ -8,7 +8,7 @@
8
8
  #
9
9
  # *****************************************************************************
10
10
 
11
- from os import path, getenv
11
+ from os import getenv
12
12
  from prompt_toolkit import prompt, print_formatted_text, HTML
13
13
  from prompt_toolkit.completion import WordCompleter
14
14
  from prompt_toolkit.validation import Validator
@@ -18,12 +18,13 @@ from .validators import YesNoValidator, FileExistsValidator, DirectoryExistsVali
18
18
  import logging
19
19
  logger = logging.getLogger(__name__)
20
20
 
21
- H1COLOR="SkyBlue"
22
- H2COLOR="SkyBlue"
23
- DESCRIPTIONCOLOR="LightSlateGrey"
24
- SUMMARYCOLOR="SkyBlue"
25
- UNDEFINEDPARAMCOLOR="LightSlateGrey"
26
- PROMPTCOLOR="Yellow"
21
+ H1COLOR = "SkyBlue"
22
+ H2COLOR = "SkyBlue"
23
+ DESCRIPTIONCOLOR = "LightSlateGrey"
24
+ SUMMARYCOLOR = "SkyBlue"
25
+ UNDEFINEDPARAMCOLOR = "LightSlateGrey"
26
+ PROMPTCOLOR = "Yellow"
27
+
27
28
 
28
29
  class PrintMixin():
29
30
  def printTitle(self, message):
@@ -67,14 +68,17 @@ class PrintMixin():
67
68
  else:
68
69
  self.printSummary(message, self.getParam(param))
69
70
 
71
+
70
72
  def masPromptYesOrNo(message):
71
73
  return HTML(f"<{PROMPTCOLOR}>{message.replace(' & ', ' &amp; ')}? [y/n]</{PROMPTCOLOR}> ")
72
74
 
75
+
73
76
  def masPromptValue(message):
74
77
  return HTML(f"<{PROMPTCOLOR}>{message.replace(' & ', ' &amp; ')}</{PROMPTCOLOR}> ")
75
78
 
79
+
76
80
  class PromptMixin():
77
- def yesOrNo(self, message: str, param: str=None) -> bool:
81
+ def yesOrNo(self, message: str, param: str = None) -> bool:
78
82
  response = prompt(masPromptYesOrNo(message), validator=YesNoValidator(), validate_while_typing=False)
79
83
  responseAsBool = response.lower() in ["y", "yes"]
80
84
 
@@ -82,7 +86,7 @@ class PromptMixin():
82
86
  self.params[param] = "true" if responseAsBool else "false"
83
87
  return responseAsBool
84
88
 
85
- def promptForString(self, message: str, param: str=None, default: str="", isPassword: bool=False, validator: Validator=None, completer: WordCompleter=None) -> str:
89
+ def promptForString(self, message: str, param: str = None, default: str = "", isPassword: bool = False, validator: Validator = None, completer: WordCompleter = None) -> str:
86
90
  if param is not None and default == "":
87
91
  default = getenv(param.upper(), default="")
88
92
 
@@ -91,7 +95,7 @@ class PromptMixin():
91
95
  self.params[param] = response
92
96
  return response
93
97
 
94
- def promptForInt(self, message: str, param: str=None, default: int=None) -> int:
98
+ def promptForInt(self, message: str, param: str = None, default: int = None) -> int:
95
99
  if param is not None and default is None:
96
100
  default = getenv(param.upper(), default=None)
97
101
 
@@ -103,12 +107,12 @@ class PromptMixin():
103
107
  self.params[param] = str(response)
104
108
  return response
105
109
 
106
- def promptForListSelect(self, message: str, options: list, param: str=None, default: int=None) -> str:
110
+ def promptForListSelect(self, message: str, options: list, param: str = None, default: int = None) -> str:
107
111
  selection = self.promptForInt(message=message, default=default)
108
112
  # List indices are 0 origin, so we need to subtract 1 from the selection made to arrive at the correct value
109
- self.setParam(param, options[selection-1])
113
+ self.setParam(param, options[selection - 1])
110
114
 
111
- def promptForFile(self, message: str, mustExist: bool=True, default: str="", envVar: str="") -> None:
115
+ def promptForFile(self, message: str, mustExist: bool = True, default: str = "", envVar: str = "") -> None:
112
116
  if default == "" and envVar != "":
113
117
  default = getenv(envVar, "")
114
118
  if mustExist:
@@ -116,7 +120,7 @@ class PromptMixin():
116
120
  else:
117
121
  return prompt(masPromptValue(message), default=default)
118
122
 
119
- def promptForDir(self, message: str, mustExist: bool=True, default: str="") -> None:
123
+ def promptForDir(self, message: str, mustExist: bool = True, default: str = "") -> None:
120
124
  if mustExist:
121
125
  return prompt(masPromptValue(message), validator=DirectoryExistsValidator(), validate_while_typing=False, default=default)
122
126
  else:
mas/cli/gencfg.py CHANGED
@@ -11,14 +11,15 @@
11
11
  from os import path
12
12
  from jinja2 import Template
13
13
 
14
+
14
15
  class ConfigGeneratorMixin():
15
16
  def generateJDBCCfg(
16
17
  self,
17
18
  instanceId: str,
18
19
  scope: str,
19
20
  destination: str,
20
- appId: str="",
21
- workspaceId: str="") -> None:
21
+ appId: str = "",
22
+ workspaceId: str = "") -> None:
22
23
 
23
24
  templateFile = path.join(self.templatesDir, "jdbccfg.yml.j2")
24
25
  with open(templateFile) as tFile:
@@ -8,4 +8,4 @@
8
8
  #
9
9
  # *****************************************************************************
10
10
 
11
- from ..cli import BaseApp
11
+ from ..cli import BaseApp # noqa: F401
mas/cli/install/app.py CHANGED
@@ -12,7 +12,7 @@
12
12
  import logging
13
13
  import logging.handlers
14
14
  from sys import exit
15
- from os import path
15
+ from os import path, getenv
16
16
  import re
17
17
 
18
18
  from openshift.dynamic.exceptions import NotFoundError
@@ -31,12 +31,12 @@ from .settings import InstallSettingsMixin
31
31
  from .summarizer import InstallSummarizerMixin
32
32
 
33
33
  from mas.cli.validators import (
34
- InstanceIDFormatValidator,
35
- WorkspaceIDFormatValidator,
36
- WorkspaceNameFormatValidator,
37
- TimeoutFormatValidator,
38
- StorageClassValidator,
39
- OptimizerInstallPlanValidator
34
+ InstanceIDFormatValidator,
35
+ WorkspaceIDFormatValidator,
36
+ WorkspaceNameFormatValidator,
37
+ TimeoutFormatValidator,
38
+ StorageClassValidator,
39
+ OptimizerInstallPlanValidator
40
40
  )
41
41
 
42
42
  from mas.devops.ocp import createNamespace, getStorageClass, getStorageClasses
@@ -116,19 +116,19 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
116
116
 
117
117
  def configICR(self):
118
118
  if self.devMode:
119
- self.setParam("mas_icr_cp", "docker-na-public.artifactory.swg-devops.com/wiotp-docker-local")
120
- self.setParam("mas_icr_cpopen", "docker-na-public.artifactory.swg-devops.com/wiotp-docker-local/cpopen")
121
- self.setParam("sls_icr_cpopen", "docker-na-public.artifactory.swg-devops.com/wiotp-docker-local/cpopen")
119
+ self.setParam("mas_icr_cp", getenv("MAS_ICR_CP", "docker-na-public.artifactory.swg-devops.com/wiotp-docker-local"))
120
+ self.setParam("mas_icr_cpopen", getenv("MAS_ICR_CPOPEN", "docker-na-public.artifactory.swg-devops.com/wiotp-docker-local/cpopen"))
121
+ self.setParam("sls_icr_cpopen", getenv("SLS_ICR_CPOPEN", "docker-na-public.artifactory.swg-devops.com/wiotp-docker-local/cpopen"))
122
122
  else:
123
- self.setParam("mas_icr_cp", "cp.icr.io/cp")
124
- self.setParam("mas_icr_cpopen", "icr.io/cpopen")
125
- self.setParam("sls_icr_cpopen", "icr.io/cpopen")
123
+ self.setParam("mas_icr_cp", getenv("MAS_ICR_CP", "cp.icr.io/cp"))
124
+ self.setParam("mas_icr_cpopen", getenv("MAS_ICR_CPOPEN", "icr.io/cpopen"))
125
+ self.setParam("sls_icr_cpopen", getenv("SLS_ICR_CPOPEN", "icr.io/cpopen"))
126
126
 
127
127
  def configICRCredentials(self):
128
128
  self.printH1("Configure IBM Container Registry")
129
129
  self.promptForString("IBM entitlement key", "ibm_entitlement_key", isPassword=True)
130
130
  if self.devMode:
131
- self.promptForString("Artifactory username", "artifactory_username", isPassword=True)
131
+ self.promptForString("Artifactory username", "artifactory_username")
132
132
  self.promptForString("Artifactory token", "artifactory_token", isPassword=True)
133
133
 
134
134
  def configCertManager(self):
@@ -145,8 +145,8 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
145
145
  print(tabulate(self.installOptions, headers="keys", tablefmt="simple_grid"))
146
146
  catalogSelection = self.promptForInt("Select catalog and release", default=1)
147
147
 
148
- self.setParam("mas_catalog_version", self.installOptions[catalogSelection-1]["catalog"])
149
- self.setParam("mas_channel", self.installOptions[catalogSelection-1]["release"])
148
+ self.setParam("mas_catalog_version", self.installOptions[catalogSelection - 1]["catalog"])
149
+ self.setParam("mas_channel", self.installOptions[catalogSelection - 1]["release"])
150
150
 
151
151
  def configSLS(self) -> None:
152
152
  self.printH1("Configure Product License")
@@ -234,7 +234,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
234
234
  "By default, Maximo Application Suite is configured with guided tour, you can disable this if it not required"
235
235
  ])
236
236
  if not self.yesOrNo("Enable Guided Tour"):
237
- self.setParam("mas_enable_walkme","false")
237
+ self.setParam("mas_enable_walkme", "false")
238
238
 
239
239
  def configMAS(self):
240
240
  self.printH1("Configure MAS Instance")
@@ -341,7 +341,8 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
341
341
  self.setParam("mas_manual_cert_mgmt", self.manualCerts)
342
342
  if self.getParam("mas_manual_cert_mgmt"):
343
343
  self.manualCertsDir = self.promptForDir("Enter the path containing the manual certificates", mustExist=True)
344
- self.setParam("mas_manual_cert_dir", self.manualCertsDir)
344
+ else:
345
+ self.manualCertsDir = None
345
346
 
346
347
  def configDNSAndCertsCloudflare(self):
347
348
  # User has chosen to set up DNS integration with Cloudflare
@@ -363,7 +364,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
363
364
  f"{self.getParam('mas_instance_id')}-cloudflare-le-stg",
364
365
  ""
365
366
  ]
366
- self.setParam("mas_cluster_issuer", certIssuerOptions[certIssuer-1])
367
+ self.setParam("mas_cluster_issuer", certIssuerOptions[certIssuer - 1])
367
368
 
368
369
  def configDNSAndCertsCIS(self):
369
370
  self.setParam("dns_provider", "cis")
@@ -384,7 +385,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
384
385
  f"{self.getParam('mas_instance_id')}-cis-le-stg",
385
386
  ""
386
387
  ]
387
- self.setParam("mas_cluster_issuer", certIssuerOptions[certIssuer-1])
388
+ self.setParam("mas_cluster_issuer", certIssuerOptions[certIssuer - 1])
388
389
 
389
390
  def configDNSAndCertsRoute53(self):
390
391
  self.setParam("dns_provider", "route53")
@@ -453,6 +454,10 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
453
454
  if self.installInspection:
454
455
  self.configAppChannel("visualinspection")
455
456
 
457
+ self.installAiBroker = self.yesOrNo("Install AI Broker")
458
+ if self.installAiBroker:
459
+ self.configAppChannel("aibroker")
460
+
456
461
  def configAppChannel(self, appId):
457
462
  versions = self.getCompatibleVersions(self.params["mas_channel"], appId)
458
463
  if len(versions) == 0:
@@ -537,8 +542,8 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
537
542
 
538
543
  def setIoTStorageClasses(self) -> None:
539
544
  if self.installIoT:
540
- self.setParam("mas_app_settings_iot_fpl_pvc_storage_class", self.getParam("storage_class_rwo"))
541
- self.setParam("mas_app_settings_iot_mqttbroker_pvc_storage_class", self.getParam("storage_class_rwo"))
545
+ self.setParam("mas_app_settings_iot_fpl_pvc_storage_class", self.getParam("storage_class_rwo"))
546
+ self.setParam("mas_app_settings_iot_mqttbroker_pvc_storage_class", self.getParam("storage_class_rwo"))
542
547
 
543
548
  def optimizerSettings(self) -> None:
544
549
  if self.installOptimizer:
@@ -568,7 +573,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
568
573
  self.promptForString("COS Provider [ibm/ocs]", "cos_type")
569
574
  if self.getParam("cos_type") == "ibm":
570
575
  self.promptForString("IBM Cloud API Key", "ibmcloud_apikey", isPassword=True)
571
- self.promptForString("IBM Cloud Resource Group", "cos_resourcegroup")
576
+ self.promptForString("IBM Cloud Resource Group", "ibmcos_resourcegroup")
572
577
 
573
578
  def interactiveMode(self) -> None:
574
579
  # Interactive mode
@@ -600,6 +605,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
600
605
  self.optimizerSettings()
601
606
  self.predictSettings()
602
607
  self.assistSettings()
608
+ self.aibrokerSettings()
603
609
 
604
610
  # Dependencies
605
611
  self.configMongoDb() # Will only do anything if IoT or Manage have been selected for install
@@ -617,7 +623,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
617
623
  self.interactiveMode = False
618
624
 
619
625
  # Set defaults
620
- self.storageClassProvider="custom"
626
+ self.storageClassProvider = "custom"
621
627
  self.installAssist = False
622
628
  self.installIoT = False
623
629
  self.installMonitor = False
@@ -625,6 +631,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
625
631
  self.installPredict = False
626
632
  self.installInspection = False
627
633
  self.installOptimizer = False
634
+ self.installAiBroker = False
628
635
  self.deployCP4D = False
629
636
  self.db2SetAffinity = False
630
637
  self.db2SetTolerations = False
@@ -660,6 +667,10 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
660
667
  "uds_contact_lastname"
661
668
  ]
662
669
  optionalParams = [
670
+ # Pipeline
671
+ "image_pull_policy",
672
+ # OpenShift
673
+ "ocp_ingress_tls_secret_name",
663
674
  # MAS
664
675
  "mas_catalog_digest",
665
676
  "mas_superuser_username",
@@ -668,9 +679,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
668
679
  "mas_app_settings_server_bundles_size",
669
680
  "mas_app_settings_default_jms",
670
681
  "mas_app_settings_persistent_volumes_flag",
671
- "mas_appws_bindings_jdbc_manage",
672
682
  "mas_app_settings_demodata",
673
- "mas_appws_components",
674
683
  "mas_app_settings_customization_archive_name",
675
684
  "mas_app_settings_customization_archive_url",
676
685
  "mas_app_settings_customization_archive_username",
@@ -686,7 +695,16 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
686
695
  "mas_app_settings_base_lang",
687
696
  "mas_app_settings_secondary_langs",
688
697
  "mas_app_settings_server_timezone",
689
- "ocp_ingress_tls_secret_name",
698
+ "mas_appws_bindings_jdbc_manage",
699
+ "mas_appws_components",
700
+ "mas_domain",
701
+ # DNS Providers
702
+ # TODO: Add CloudFlare and Route53 support
703
+ "dns_provider",
704
+ "cis_email",
705
+ "cis_apikey",
706
+ "cis_crn",
707
+ "cis_subdomain",
690
708
  # DRO
691
709
  "dro_namespace",
692
710
  # MongoDb
@@ -733,7 +751,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
733
751
  "eventstreams_instance_location",
734
752
  # COS
735
753
  "cos_type",
736
- "cos_resourcegroup",
754
+ "ibmcos_resourcegroup",
737
755
  # ECK
738
756
  "eck_action",
739
757
  "eck_enable_logstash",
@@ -760,6 +778,29 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
760
778
  "mas_arcgis_channel",
761
779
  # Guided Tour
762
780
  "mas_enable_walkme",
781
+ # Aibroker
782
+ "mas_aibroker_storage_provider",
783
+ "mas_aibroker_storage_accesskey",
784
+ "mas_aibroker_storage_secretkey",
785
+ "mas_aibroker_storage_host",
786
+ "mas_aibroker_storage_port",
787
+ "mas_aibroker_storage_ssl",
788
+ "mas_aibroker_storage_region",
789
+ "mas_aibroker_storage_pipelines_bucket",
790
+ "mas_aibroker_storage_tenants_bucket",
791
+ "mas_aibroker_storage_templates_bucket",
792
+ "mas_aibroker_tenant_name",
793
+ "mas_aibroker_watsonxai_apikey",
794
+ "mas_aibroker_watsonxai_url",
795
+ "mas_aibroker_watsonxai_project_id",
796
+ "mas_aibroker_watsonx_action",
797
+ "mas_aibroker_db_host",
798
+ "mas_aibroker_db_port",
799
+ "mas_aibroker_db_user",
800
+ "mas_aibroker_db_database",
801
+ "mas_aibroker_db_secret_name",
802
+ "mas_aibroker_db_secret_key",
803
+ "mas_aibroker_db_secret_value",
763
804
  # Special chars
764
805
  "mas_special_characters"
765
806
  ]
@@ -808,37 +849,44 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
808
849
  else:
809
850
  self.setParam("mas_pod_templates_dir", value)
810
851
 
852
+ # We check for both None and "" values for the application channel parameters
853
+ # value = None means the parameter wasn't set at all
854
+ # value = "" means the paramerter was explicitly set to "don't install this application"
811
855
  elif key == "assist_channel":
812
- if value is not None:
856
+ if value is not None and value != "":
813
857
  self.setParam("mas_app_channel_assist", value)
814
858
  self.installAssist = True
815
859
  elif key == "iot_channel":
816
- if value is not None:
860
+ if value is not None and value != "":
817
861
  self.setParam("mas_app_channel_iot", value)
818
862
  self.installIoT = True
819
863
  elif key == "monitor_channel":
820
- if value is not None:
864
+ if value is not None and value != "":
821
865
  self.setParam("mas_app_channel_monitor", value)
822
866
  self.installMonitor = True
823
867
  elif key == "manage_channel":
824
- if value is not None:
868
+ if value is not None and value != "":
825
869
  self.setParam("mas_app_channel_manage", value)
826
870
  self.installManage = True
827
871
  elif key == "predict_channel":
828
- if value is not None:
872
+ if value is not None and value != "":
829
873
  self.setParam("mas_app_channel_predict", value)
830
874
  self.installPredict = True
831
875
  self.deployCP4D = True
832
876
  elif key == "visualinspection_channel":
833
- if value is not None:
877
+ if value is not None and value != "":
834
878
  self.setParam("mas_app_channel_visualinspection", value)
835
879
  self.installInspection = True
880
+ elif key == "aibroker_channel":
881
+ if value is not None and value != "":
882
+ self.setParam("mas_app_channel_aibroker", value)
883
+ self.installAiBroker = True
836
884
  elif key == "optimizer_channel":
837
- if value is not None:
885
+ if value is not None and value != "":
838
886
  self.setParam("mas_app_channel_optimizer", value)
839
887
  self.installOptimizer = True
840
888
  elif key == "optimizer_plan":
841
- if value is not None:
889
+ if value is not None and value != "":
842
890
  self.setParam("mas_app_plan_optimizer", value)
843
891
 
844
892
  # Manage advanced settings that need extra processing
@@ -858,9 +906,9 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
858
906
  self.fatalError(f"{key} must be set")
859
907
  self.pipelineStorageClass = value
860
908
  elif key == "license_file":
861
- if value is None:
862
- self.fatalError(f"{key} must be set")
863
- self.slsLicenseFileLocal = value
909
+ if value is None:
910
+ self.fatalError(f"{key} must be set")
911
+ self.slsLicenseFileLocal = value
864
912
 
865
913
  elif key.startswith("approval_"):
866
914
  if key not in self.approvals:
@@ -876,7 +924,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
876
924
  self.approvals[key]["maxRetries"] = int(valueParts[1])
877
925
  self.approvals[key]["retryDelay"] = int(valueParts[2])
878
926
  self.approvals[key]["ignoreFailure"] = bool(valueParts[3])
879
- except:
927
+ except ValueError:
880
928
  self.fatalError(f"Unsupported format for {key} ({value}). Expected string:int:int:boolean")
881
929
 
882
930
  # Arguments that we don't need to do anything with
@@ -886,9 +934,10 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
886
934
  elif key == "manual_certificates":
887
935
  if value is not None:
888
936
  self.setParam("mas_manual_cert_mgmt", True)
889
- self.setParam("mas_manual_cert_dir", value)
937
+ self.manualCertsDir = value
890
938
  else:
891
939
  self.setParam("mas_manual_cert_mgmt", False)
940
+ self.manualCertsDir = None
892
941
 
893
942
  # Fail if there's any arguments we don't know how to handle
894
943
  else:
@@ -938,7 +987,8 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
938
987
  "monitor": "9.0.3",
939
988
  "optimizer": "9.0.3",
940
989
  "predict": "9.0.2",
941
- "inspection": "9.0.3"
990
+ "inspection": "9.0.3",
991
+ "aibroker": "9.0.2"
942
992
  },
943
993
  {
944
994
  "#": 2,
@@ -965,7 +1015,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
965
1015
  "optimizer": "8.4.10",
966
1016
  "predict": "8.8.3",
967
1017
  "inspection": "8.8.4"
968
- },
1018
+ },
969
1019
  {
970
1020
  "#": 4,
971
1021
  "catalog": "v9-240827-amd64",
@@ -1120,7 +1170,7 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
1120
1170
 
1121
1171
  with Halo(text='Validating OpenShift Pipelines installation', spinner=self.spinner) as h:
1122
1172
  installOpenShiftPipelines(self.dynamicClient)
1123
- h.stop_and_persist(symbol=self.successIcon, text=f"OpenShift Pipelines Operator is installed and ready to use")
1173
+ h.stop_and_persist(symbol=self.successIcon, text="OpenShift Pipelines Operator is installed and ready to use")
1124
1174
 
1125
1175
  with Halo(text=f'Preparing namespace ({pipelinesNamespace})', spinner=self.spinner) as h:
1126
1176
  createNamespace(self.dynamicClient, pipelinesNamespace)
@@ -1144,9 +1194,9 @@ class InstallApp(BaseApp, InstallSettingsMixin, InstallSummarizerMixin, ConfigGe
1144
1194
 
1145
1195
  h.stop_and_persist(symbol=self.successIcon, text=f"Namespace is ready ({pipelinesNamespace})")
1146
1196
 
1147
- with Halo(text=f'Testing availability of MAS CLI image in cluster', spinner=self.spinner) as h:
1197
+ with Halo(text='Testing availability of MAS CLI image in cluster', spinner=self.spinner) as h:
1148
1198
  testCLI()
1149
- h.stop_and_persist(symbol=self.successIcon, text=f"MAS CLI image deployment test completed")
1199
+ h.stop_and_persist(symbol=self.successIcon, text="MAS CLI image deployment test completed")
1150
1200
 
1151
1201
  with Halo(text=f'Installing latest Tekton definitions (v{self.version})', spinner=self.spinner) as h:
1152
1202
  updateTektonDefinitions(pipelinesNamespace, self.tektonDefsPath)