diff --git a/.secrets.baseline b/.secrets.baseline index be9942aed5..a8f0c1ddd8 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "build/bin/config/oscap/ssg-rhel9-ds.xml|^.secrets.baseline$|^docs/catalogs/", "lines": null }, - "generated_at": "2026-07-24T11:52:31Z", + "generated_at": "2026-07-31T14:03:18Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -270,7 +270,7 @@ "hashed_secret": "b2817467154949a61f8e9ad31d1eeaf03221cbfa", "is_secret": false, "is_verified": false, - "line_number": 387, + "line_number": 392, "type": "Secret Keyword", "verified_result": null } diff --git a/image/cli/mascli/functions/gitops_aiservice_tenant b/image/cli/mascli/functions/gitops_aiservice_tenant index a3654bfc3d..bf51085662 100644 --- a/image/cli/mascli/functions/gitops_aiservice_tenant +++ b/image/cli/mascli/functions/gitops_aiservice_tenant @@ -28,7 +28,8 @@ ibm_aiservice_tenant(required): --aiservice-watsonxai-url ${COLOR_YELLOW}AISERVICE_WATSONXAI_URL${TEXT_RESET} Endpoint URL for Watsonx.ai --aiservice-watsonx-full ${COLOR_YELLOW}AISERVICE_WATSONX_FULL${TEXT_RESET} Full URL for Watsonx.ai including API key --tenant-scheduling-config-file ${COLOR_YELLOW}TENANT_SCHEDULING_CONFIG_FILE${TEXT_RESET} Path to tenant scheduling configuration file (tolerations and nodeSelector) - --enable-deprovisioning ${COLOR_YELLOW}AISERVICE_ENABLE_DEPROVISIONING${TEXT_RESET} When true, the tenant is deprovisioned when its AIServiceTenant CR is deleted + --tenant-operator-config-file ${COLOR_YELLOW}TENANT_OPERATOR_CONFIG_FILE${TEXT_RESET} Path to tenant operator configuration file + --enable-deprovisioning ${COLOR_YELLOW}AISERVICE_ENABLE_DEPROVISIONING${TEXT_RESET} When true, the tenant is deprovisioned when its AIServiceTenant CR is deleted AiService : --aiservice-namespace ${COLOR_YELLOW}AISERVICE_NAMESPACE${TEXT_RESET} The namespace where AI Service is deployed @@ -270,6 +271,10 @@ function gitops_aiservice_tenant_noninteractive() { --tenant-scheduling-config-yaml) export TENANT_SCHEDULING_CONFIG_YAML=$1 && shift ;; + + --tenant-operator-config-file) + export TENANT_OPERATOR_CONFIG_FILE=$1 && shift + ;; --enable-deprovisioning) export AISERVICE_ENABLE_DEPROVISIONING=$1 && shift @@ -424,6 +429,12 @@ else echo_reset_dim "Scheduling constraints (tolerations/nodeSelector) .............. ${COLOR_MAGENTA}Not Configured" fi + if [[ -n "$TENANT_OPERATOR_CONFIG_FILE" ]]; then + echo_reset_dim "Tenant operator configuration file .............. ${COLOR_MAGENTA}${TENANT_OPERATOR_CONFIG_FILE}" + else + echo_reset_dim "Tenant operator configuration file .............. ${COLOR_MAGENTA}Not set" + fi + echo_reset_dim "MAS ICR CP registry ............................................ ${COLOR_MAGENTA}${MAS_ICR_CP}" echo_reset_dim "MAS ICR CPOPEN registry ........................................ ${COLOR_MAGENTA}${MAS_ICR_CPOPEN}" @@ -517,6 +528,11 @@ fi export TENANT_SCHEDULING_CONFIG=$(yq eval '.' ${TENANT_SCHEDULING_CONFIG_YAML}) echo -e "\n - TENANT_SCHEDULING_CONFIG content .................. ${TENANT_SCHEDULING_CONFIG}" fi + + if [[ -n "$TENANT_OPERATOR_CONFIG_FILE" && -s "$TENANT_OPERATOR_CONFIG_FILE" ]]; then + export TENANT_OPERATOR_CONFIG=$(yq eval '.' ${TENANT_OPERATOR_CONFIG_FILE}) + echo -e "\n - TENANT_OPERATOR_CONFIG .................. ${TENANT_OPERATOR_CONFIG}" + fi # finally push them into the git repo diff --git a/image/cli/mascli/templates/gitops/appset-configs/cluster/instance/ibm-aiservice-tenant.yaml.j2 b/image/cli/mascli/templates/gitops/appset-configs/cluster/instance/ibm-aiservice-tenant.yaml.j2 index 668762eff7..fd11afca04 100644 --- a/image/cli/mascli/templates/gitops/appset-configs/cluster/instance/ibm-aiservice-tenant.yaml.j2 +++ b/image/cli/mascli/templates/gitops/appset-configs/cluster/instance/ibm-aiservice-tenant.yaml.j2 @@ -65,3 +65,8 @@ ibm_aiservice_tenant: tenant_scheduling_config: {{ TENANT_SCHEDULING_CONFIG | indent(4)}} {% endif %} + +{% if TENANT_OPERATOR_CONFIG is defined and TENANT_OPERATOR_CONFIG != '' %} + tenant_operator_config: + {{ TENANT_OPERATOR_CONFIG | indent(4)}} +{% endif %} diff --git a/python/src/mas/cli/aiservice/install/app.py b/python/src/mas/cli/aiservice/install/app.py index db3fd0ac28..42f6c2d385 100644 --- a/python/src/mas/cli/aiservice/install/app.py +++ b/python/src/mas/cli/aiservice/install/app.py @@ -189,6 +189,7 @@ def nonInteractiveMode(self) -> None: self.db2LicenseFileLocal = None self.aiserviceTenantSchedulingConfigFileLocal = None + self.aiserviceTenantOperatorConfigFileLocal = None self.approvals = { "approval_aiservice": {"id": "aiservice"}, @@ -278,6 +279,10 @@ def nonInteractiveMode(self) -> None: if value is not None and value != "": self.aiserviceTenantSchedulingConfigFileLocal = value + elif key == "tenant_operator_config_file": + if value is not None and value != "": + self.aiserviceTenantOperatorConfigFileLocal = value + elif key == "db2_action_aiservice": # Check if external DB parameters are provided externalDbParams = ["aiservice_db_jdbc_url", "aiservice_db_username", "aiservice_db_password"] @@ -718,7 +723,9 @@ def aiServiceTenantSettings(self) -> None: self.promptForString("Entitlement end date (YYYY-MM-DD)", "tenant_entitlement_end_date", default=oneyear.strftime("%Y-%m-%d")) self.aiserviceTenantSchedulingConfigFileLocal = None + self.aiserviceTenantOperatorConfigFileLocal = None self.configSchedulingConstraints() + self.configTenantOperator() @logMethodCall def configSchedulingConstraints(self): diff --git a/python/src/mas/cli/aiservice/install/argBuilder.py b/python/src/mas/cli/aiservice/install/argBuilder.py index da1df2df69..1cf4854681 100644 --- a/python/src/mas/cli/aiservice/install/argBuilder.py +++ b/python/src/mas/cli/aiservice/install/argBuilder.py @@ -174,6 +174,8 @@ def buildCommand(self) -> str: command += f" --tenant-entitlement-end-date \"{self.getParam('tenant_entitlement_end_date')}\"{newline}" if self.aiserviceTenantSchedulingConfigFileLocal: command += f' --tenant-scheduling-config-file "{self.aiserviceTenantSchedulingConfigFileLocal}"{newline}' + if self.aiserviceTenantOperatorConfigFileLocal: + command += f' --tenant-operator-config-file "{self.aiserviceTenantOperatorConfigFileLocal}"{newline}' if self.getParam("rsl_ca_crt") != "": command += f" --rsl-ca-crt \"{self.getParam('rsl_ca_crt')}\"{newline}" diff --git a/python/src/mas/cli/aiservice/install/argParser.py b/python/src/mas/cli/aiservice/install/argParser.py index 65f9550d64..3935d8f194 100644 --- a/python/src/mas/cli/aiservice/install/argParser.py +++ b/python/src/mas/cli/aiservice/install/argParser.py @@ -222,6 +222,13 @@ def isValidFile(parser, arg) -> str: help="Path to the YAML file that contains the scheduling configuration for tenant", type=lambda x: isValidFile(aiServiceinstallArgParser, x), ) +aiserviceAdvancedArgGroup.add_argument( + "--tenant-operator-config-file", + dest="tenant_operator_config_file", + required=False, + help="Path to the YAML file that contains the tenant operator customization settings", + type=lambda x: isValidFile(aiServiceinstallArgParser, x), +) # Database Configuration diff --git a/python/src/mas/cli/aiservice/install/summarizer.py b/python/src/mas/cli/aiservice/install/summarizer.py index 05a1a022f7..a4cefa1f64 100644 --- a/python/src/mas/cli/aiservice/install/summarizer.py +++ b/python/src/mas/cli/aiservice/install/summarizer.py @@ -61,6 +61,9 @@ def aiServiceSummary(self) -> None: if self.aiserviceTenantSchedulingConfigFileLocal: self.printSummary("Scheduling configuration file", self.aiserviceTenantSchedulingConfigFileLocal) + if self.aiserviceTenantOperatorConfigFileLocal: + self.printSummary("Tenant operator configuration file", self.aiserviceTenantOperatorConfigFileLocal) + self.printH2("S3 Configuration") # self.printParamSummary("Storage provider", "aiservice_s3_provider") if self.getParam("minio_root_user") is not None and self.getParam("minio_root_user") != "": diff --git a/python/src/mas/cli/install/app.py b/python/src/mas/cli/install/app.py index d560933691..4f76437ea5 100644 --- a/python/src/mas/cli/install/app.py +++ b/python/src/mas/cli/install/app.py @@ -1879,7 +1879,9 @@ def aiServiceTenantSettings(self) -> None: ) self.aiserviceTenantSchedulingConfigFileLocal = None + self.aiserviceTenantOperatorConfigFileLocal = None self.configSchedulingConstraints() + self.configTenantOperator() @logMethodCall def configSchedulingConstraints(self): @@ -2005,6 +2007,7 @@ def chooseInstallFlavour(self) -> None: " - Choose alternative Apache Kafka providers (default to Strimzi)", " - Customize Grafana storage settings", " - Customize Scheduling configuration for AI workloads(Training pipeline & Inference services) for AI Service tenant", + " - Customize AI Service tenant operator configuration", ] ) self.showAdvancedOptions = self.yesOrNo("Show advanced installation options") @@ -2018,6 +2021,7 @@ def interactiveMode(self, simplified: bool, advanced: bool) -> None: self.slsLicenseFileLocal = None self.db2LicenseFileLocal = None self.aiserviceTenantSchedulingConfigFileLocal = None + self.aiserviceTenantOperatorConfigFileLocal = None self.facilitiesPropertiesFileLocal = None if simplified: @@ -2111,6 +2115,7 @@ def nonInteractiveMode(self) -> None: self.slsLicenseFileLocal = None self.db2LicenseFileLocal = None self.aiserviceTenantSchedulingConfigFileLocal = None + self.aiserviceTenantOperatorConfigFileLocal = None self.facilitiesPropertiesFileLocal = None self.approvals: Dict[str, Dict[str, Any]] = { @@ -2466,6 +2471,10 @@ def nonInteractiveMode(self) -> None: if value is not None and value != "": self.aiserviceTenantSchedulingConfigFileLocal = value + elif key == "tenant_operator_config_file": + if value is not None and value != "": + self.aiserviceTenantOperatorConfigFileLocal = value + # Fail if there's any arguments we don't know how to handle else: print(f"Unknown option: {key} {value}") diff --git a/python/src/mas/cli/install/argBuilder.py b/python/src/mas/cli/install/argBuilder.py index 1b227ff981..ff9463d884 100644 --- a/python/src/mas/cli/install/argBuilder.py +++ b/python/src/mas/cli/install/argBuilder.py @@ -480,6 +480,8 @@ def buildCommand(self) -> str: command += f" --tenant-entitlement-end-date \"{self.getParam('tenant_entitlement_end_date')}\"{newline}" if self.aiserviceTenantSchedulingConfigFileLocal: command += f' --tenant-scheduling-config-file "{self.aiserviceTenantSchedulingConfigFileLocal}"{newline}' + if self.aiserviceTenantOperatorConfigFileLocal: + command += f' --tenant-operator-config-file "{self.aiserviceTenantOperatorConfigFileLocal}"{newline}' if self.getParam("rsl_ca_crt") != "": command += f" --rsl-ca-crt \"{self.getParam('rsl_ca_crt')}\"{newline}" diff --git a/python/src/mas/cli/install/argParser.py b/python/src/mas/cli/install/argParser.py index 173d1257d1..bc0a5c6850 100644 --- a/python/src/mas/cli/install/argParser.py +++ b/python/src/mas/cli/install/argParser.py @@ -1104,6 +1104,13 @@ def isValidFile(parser: argparse.ArgumentParser, arg: str) -> str: help="Path to the YAML file that contains the scheduling configuration for tenant", type=lambda x: isValidFile(installArgParser, x), ) +aiServiceArgGroup.add_argument( + "--tenant-operator-config-file", + dest="tenant_operator_config_file", + required=False, + help="Path to the YAML file that contains the tenant operator customization settings", + type=lambda x: isValidFile(installArgParser, x), +) # IBM Cloud Pak for Data # ----------------------------------------------------------------------------- diff --git a/python/src/mas/cli/install/settings/additionalConfigs.py b/python/src/mas/cli/install/settings/additionalConfigs.py index 96abce3fe2..197bded9bb 100644 --- a/python/src/mas/cli/install/settings/additionalConfigs.py +++ b/python/src/mas/cli/install/settings/additionalConfigs.py @@ -38,6 +38,7 @@ class AdditionalConfigsMixin: manualCertsDir: str | None showAdvancedOptions: bool aiserviceTenantSchedulingConfigFileLocal: str | None + aiserviceTenantOperatorConfigFileLocal: str | None additionalConfigsSecret: Dict[str, Any] | None podTemplatesSecret: Dict[str, Any] | None slsLicenseFileSecret: Dict[str, Any] | None @@ -211,12 +212,16 @@ def slsLicenseFile(self) -> None: def aiserviceConfig(self) -> None: self.aiserviceConfigSecret = None + aiserviceConfigSecret: dict[str, Any] = {"apiVersion": "v1", "kind": "Secret", "type": "Opaque", "metadata": {"name": "pipeline-aiservice-config"}} if self.aiserviceTenantSchedulingConfigFileLocal: - aiserviceConfigSecret: dict[str, Any] = {"apiVersion": "v1", "kind": "Secret", "type": "Opaque", "metadata": {"name": "pipeline-aiservice-config"}} self.setParam("tenant_scheduling_config_file", f"/workspace/aiservice/{path.basename(self.aiserviceTenantSchedulingConfigFileLocal)}") self.aiserviceConfigSecret = self.addFilesToSecret(aiserviceConfigSecret, self.aiserviceTenantSchedulingConfigFileLocal, "yaml") + if self.aiserviceTenantOperatorConfigFileLocal: + self.setParam("tenant_operator_config_file", f"/workspace/aiservice/{path.basename(self.aiserviceTenantOperatorConfigFileLocal)}") + self.aiserviceConfigSecret = self.addFilesToSecret(aiserviceConfigSecret, self.aiserviceTenantOperatorConfigFileLocal, "yaml") + def db2LicenseFile(self) -> None: if self.db2LicenseFileLocal: db2LicenseFileSecret = {"apiVersion": "v1", "kind": "Secret", "type": "Opaque", "metadata": {"name": "pipeline-db2-license"}} diff --git a/python/src/mas/cli/install/settings/aiSettings.py b/python/src/mas/cli/install/settings/aiSettings.py index 86f09b19e5..4020e0129e 100644 --- a/python/src/mas/cli/install/settings/aiSettings.py +++ b/python/src/mas/cli/install/settings/aiSettings.py @@ -11,6 +11,7 @@ from os import path from typing import TYPE_CHECKING, Dict, List, Any from prompt_toolkit import print_formatted_text +from mas.cli.cli import logMethodCall if TYPE_CHECKING: # Type hints for methods and attributes provided by other mixins @@ -29,6 +30,7 @@ class AiSettingsMixin: templatesDir: str dynamicClient: Any installAIService: bool + aiserviceTenantOperatorConfigFileLocal: str | None # Methods from BaseApp def setParam(self, param: str, value: str) -> None: ... @@ -55,6 +57,8 @@ def promptForString( completer: WordCompleter | None = None, ) -> str: ... + def promptForFile(self, message: str, mustExist: bool = True, default: str = "", envVar: str = "") -> str: ... + def promptForListSelect(self, message: str, options: List[str], param: str | None = None, default: int | None = None) -> str: ... # Methods from ConfigGeneratorMixin or InstallSettingsMixin @@ -142,3 +146,21 @@ def configAi(self) -> None: else: self.setParam("configure_aiassistant", "none") print_formatted_text("AiCfg configuration skipped") + + @logMethodCall + def configTenantOperator(self): + if self.showAdvancedOptions: + self.printH1("Tenant operator configuration customization") + self.printDescription( + content=[ + "The AI Service tenant operator deployment may be customized, for example, to adjust resource requests/limits", + "To customize the operator, create a YAML configuration file", + "The YAML file may contain any valid configuration for the 'spec.config' field in an OLM Subscription resource", + ] + ) + + configTenantOperator = self.yesOrNo("Customize the AI Service tenant operator deployment") + if configTenantOperator: + self.aiserviceTenantOperatorConfigFileLocal = self.promptForFile( + "Tenant operator configuration YAML file", mustExist=True, envVar="AISERVICE_TENANT_OPERATOR_CONFIG_FILE" + ) diff --git a/python/src/mas/cli/install/summarizer.py b/python/src/mas/cli/install/summarizer.py index 08bb2a50d2..0bda7a8190 100644 --- a/python/src/mas/cli/install/summarizer.py +++ b/python/src/mas/cli/install/summarizer.py @@ -37,6 +37,7 @@ class InstallSummarizerMixin: localConfigDir: str | None slsLicenseFileLocal: str | None aiserviceTenantSchedulingConfigFileLocal: str | None + aiserviceTenantOperatorConfigFileLocal: str | None facilitiesPropertiesFileLocal: str | None deployCP4D: bool installAssist: bool @@ -413,6 +414,11 @@ def aiServiceSummary(self) -> None: "Scheduling configuration file", self.aiserviceTenantSchedulingConfigFileLocal, ) + if self.aiserviceTenantOperatorConfigFileLocal: + self.printSummary( + "Tenant operator configuration file", + self.aiserviceTenantOperatorConfigFileLocal, + ) self.printH2("S3 Configuration") # self.printParamSummary("Storage provider", "aiservice_s3_provider") diff --git a/python/tests/integration/aiservice_install/test_app.py b/python/tests/integration/aiservice_install/test_app.py index 976f381b99..f4715fdf26 100644 --- a/python/tests/integration/aiservice_install/test_app.py +++ b/python/tests/integration/aiservice_install/test_app.py @@ -26,6 +26,7 @@ def test_install_noninteractive(tmpdir): tmpdir.join("authorized_entitlement.lic").write("testLicense") tmpdir.join("aiservice-tenant-affinity-config.yaml").write("#") + tmpdir.join("aiservice-tenant-operator-config.yaml").write("#") with mock.patch("mas.cli.cli.config"): dynamic_client = MagicMock(DynamicClient) resources = MagicMock() @@ -154,6 +155,8 @@ def test_install_noninteractive(tmpdir): "2026-08-28", "--tenant-scheduling-config-file", f"{tmpdir}/aiservice-tenant-affinity-config.yaml", + "--tenant-operator-config-file", + f"{tmpdir}/aiservice-tenant-operator-config.yaml", "--rsl-ca-crt", "testRslCaCert", "--accept-license", @@ -166,6 +169,7 @@ def test_install_noninteractive(tmpdir): def test_install_interactive_advanced(tmpdir): tmpdir.join("authorized_entitlement.lic").write("testLicense") tmpdir.join("aiservice-tenant-affinity-config.yaml").write("#") + tmpdir.join("aiservice-tenant-operator-config.yaml").write("#") tmpdir.join("mongodb-system.yaml").write("#") tmpdir.join("cert.crt").write("#") with mock.patch("mas.cli.cli.config"): @@ -259,6 +263,10 @@ def set_mixin_prompt_input(**kwargs): return "y" if re.match(".*Scheduling configuration YAML file.*", message): return f"{tmpdir}/aiservice-tenant-affinity-config.yaml" + if re.match(".*Customize the AI Service tenant operator deployment.*", message): + return "y" + if re.match(".*Tenant operator configuration YAML file.*", message): + return f"{tmpdir}/aiservice-tenant-operator-config.yaml" if re.match(".*Watsonxai api key.*", message): return "testWxApiKey" if re.match(".*Watsonxai machine learning url.*", message): diff --git a/tekton/src/params/install-aiservice.yml.j2 b/tekton/src/params/install-aiservice.yml.j2 index f99aaa077b..b1d8eb65be 100644 --- a/tekton/src/params/install-aiservice.yml.j2 +++ b/tekton/src/params/install-aiservice.yml.j2 @@ -104,6 +104,10 @@ type: string description: Path to YAML file that contains scheduling constraints for AI workloads for tenant default: "" +- name: tenant_operator_cfg_file + type: string + description: Path to YAML file that contains tenant operator customization settings + default: "" # MAS Application Configuration - IBM Maximo AI Service - Watstonx # ----------------------------------------------------------------------------- diff --git a/tekton/src/pipelines/gitops/gitops-aiservice-tenant-pipeline.yml.j2 b/tekton/src/pipelines/gitops/gitops-aiservice-tenant-pipeline.yml.j2 index 22f67a0487..5b7d422541 100644 --- a/tekton/src/pipelines/gitops/gitops-aiservice-tenant-pipeline.yml.j2 +++ b/tekton/src/pipelines/gitops/gitops-aiservice-tenant-pipeline.yml.j2 @@ -97,6 +97,9 @@ spec: - name: tenant_scheduling_config_yaml type: string default: "" + - name: tenant_operator_config + type: string + default: "" # standalone sls - name: sls_service @@ -204,5 +207,7 @@ spec: value: $(params.tenant_entitlement_end_date) - name: tenant_scheduling_config_yaml value: $(params.tenant_scheduling_config_yaml) + - name: tenant_operator_config + value: $(params.tenant_operator_config) - name: sls_service value: $(params.sls_service) \ No newline at end of file diff --git a/tekton/src/pipelines/taskdefs/aiservice/aiservice.yml.j2 b/tekton/src/pipelines/taskdefs/aiservice/aiservice.yml.j2 index 1792cac2ec..c4f1d79634 100644 --- a/tekton/src/pipelines/taskdefs/aiservice/aiservice.yml.j2 +++ b/tekton/src/pipelines/taskdefs/aiservice/aiservice.yml.j2 @@ -95,6 +95,9 @@ - name: tenant_scheduling_cfg_file value: $(params.tenant_scheduling_cfg_file) + - name: tenant_operator_cfg_file + value: $(params.tenant_operator_cfg_file) + # Database Configuration - name: install_db2 value: $(params.install_db2) diff --git a/tekton/src/tasks/aiservice/aiservice.yml.j2 b/tekton/src/tasks/aiservice/aiservice.yml.j2 index 3f7ca841d1..1901701e30 100644 --- a/tekton/src/tasks/aiservice/aiservice.yml.j2 +++ b/tekton/src/tasks/aiservice/aiservice.yml.j2 @@ -136,6 +136,9 @@ spec: - name: tenant_scheduling_cfg_file type: string + - name: tenant_operator_cfg_file + type: string + # RSL - name: rsl_ca_crt type: string @@ -266,6 +269,9 @@ spec: value: $(params.tenant_entitlement_end_date) - name: AISERVICE_TENANT_SCHEDULING_CONFIG_FILE value: $(params.tenant_scheduling_cfg_file) + + - name: AISERVICE_TENANT_OPERATOR_CONFIG_FILE + value: $(params.tenant_operator_cfg_file) # RSL - name: RSL_CA_CRT diff --git a/tekton/src/tasks/gitops/gitops-aiservice-tenant.yml.j2 b/tekton/src/tasks/gitops/gitops-aiservice-tenant.yml.j2 index fd04a82ac6..316eac06f7 100644 --- a/tekton/src/tasks/gitops/gitops-aiservice-tenant.yml.j2 +++ b/tekton/src/tasks/gitops/gitops-aiservice-tenant.yml.j2 @@ -93,6 +93,9 @@ spec: type: string - name: tenant_scheduling_config_yaml type: string + - name: tenant_operator_config + type: string + default: "" - name: sls_service type: string default: "" @@ -185,6 +188,8 @@ spec: value: $(params.tenant_entitlement_end_date) - name: TENANT_SCHEDULING_CONFIG_YAML value: $(params.tenant_scheduling_config_yaml) + - name: TENANT_OPERATOR_CONFIG + value: $(params.tenant_operator_config) - name: STANDALONE_SLS_SERVICE value: $(params.sls_service) - name: IS_GITOPS_FVT_ENV