From 71c2d5599f8c5389bc003f242c2d774ec4799f10 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Thu, 20 Nov 2025 17:49:46 +0530 Subject: [PATCH 01/27] [minor] Add AI Service configuration role for Manage --- .../tasks/manage/post-config/main.yml | 10 + .../suite_manage_aiservice_config/README.md | 48 ++++ .../defaults/main.yml | 19 ++ .../meta/main.yml | 15 ++ .../tasks/configure.yml | 237 ++++++++++++++++++ .../tasks/main.yml | 76 ++++++ .../templates/configmap.yml.j2 | 14 ++ 7 files changed, 419 insertions(+) create mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/README.md create mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml create mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml create mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml create mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml create mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml index dc26e069db..2d84d76f60 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml @@ -14,6 +14,7 @@ - "COS Instance Name ...................... {{ cos_instance_name }}" - "COS Bucket Name ........................ {{ cos_bucket_name }}" - "IBM Cloud Resource Group ............... {{ ibmcloud_resourcegroup }}" + - "AI Service Instance ID ................. {{ aiservice_instance_id | default('Not configured', true) }}" # Manage post-configuration: Image stitching - name: "Run Manage post-configuration: Set up image stitching" @@ -42,3 +43,12 @@ when: - mas_manage_attachment_configuration_mode in ["db", "cr"] - mas_manage_attachments_provider in ["filestorage", "ibm", "aws"] + +# Manage post-configuration: AI Service +- name: "Run Manage post-configuration: Set up AI Service integration" + include_role: + name: ibm.mas_devops.suite_manage_aiservice_config + when: + - mas_manage_attachment_configuration_mode == "aiservice" + - aiservice_instance_id is defined + - aiservice_instance_id != "" diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md b/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md new file mode 100644 index 0000000000..874497be0b --- /dev/null +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md @@ -0,0 +1,48 @@ +suite_manage_aiservice_config +=============================================================================== + +This role configures AI Service integration for Maximo Manage by: +1. Retrieving AI Service connection details (API key, URL, tenant ID) +2. Patching these properties into the Manage encryption secret +3. Triggering Manage restart to apply the configuration + +Role Variables +------------------------------------------------------------------------------- + +### Required Variables + +- `mas_instance_id`: MAS instance ID +- `mas_workspace_id`: MAS workspace ID +- `aiservice_instance_id`: AI Service instance ID + +### Optional Variables + +- `mas_app_id`: Application ID (default: `manage`) +- `mas_manage_aiservice_configuration_mode`: Configuration mode (default: empty string) + +Example Playbook +------------------------------------------------------------------------------- + +```yaml +- hosts: localhost + vars: + mas_instance_id: "mymas" + mas_workspace_id: "masdev" + aiservice_instance_id: "mymas" + mas_manage_aiservice_configuration_mode: "aiservice" + roles: + - ibm.mas_devops.suite_manage_aiservice_config +``` + +Environment Variables +------------------------------------------------------------------------------- + +- `MAS_INSTANCE_ID`: MAS instance ID +- `MAS_WORKSPACE_ID`: MAS workspace ID +- `AISERVICE_INSTANCE_ID`: AI Service instance ID +- `MAS_APP_ID`: Application ID (default: `manage`) +- `MAS_MANAGE_AISERVICE_CONFIGURATION_MODE`: Configuration mode + +License +------------------------------------------------------------------------------- +EPL-2.0 \ No newline at end of file diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml new file mode 100644 index 0000000000..e0a41fc4ef --- /dev/null +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml @@ -0,0 +1,19 @@ +--- +# The following MAS information is needed to lookup the right Manage app instance +mas_instance_id: "{{ lookup('env', 'MAS_INSTANCE_ID') }}" +mas_workspace_id: "{{ lookup('env', 'MAS_WORKSPACE_ID') | default('masdev', true) }}" +mas_app_id: "{{ lookup('env', 'MAS_APP_ID') | default('manage', true) }}" + +# AI Service instance information +aiservice_instance_id: "{{ lookup('env', 'AISERVICE_INSTANCE_ID') }}" + +# AI Service namespace +aiservice_namespace: "aiservice-{{ aiservice_instance_id }}" + +# Manage namespace +manage_namespace: "mas-{{ mas_instance_id }}-{{ mas_app_id }}" + +# Manage encryption secret name +# This is the secret where AI Service properties will be stored +manage_encryption_secret_name: "{{ mas_workspace_id }}-manage-encryptionsecret" + diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml new file mode 100644 index 0000000000..2cfcdafd7e --- /dev/null +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml @@ -0,0 +1,15 @@ +--- +galaxy_info: + author: Divyesh Khokhar(@Divyesh-Khokhar) + description: Configure AI Service integration for Maximo Manage + company: IBM + license: EPL-2.0 + min_ansible_version: "2.10" + platforms: + - name: EL + versions: + - "8" + +dependencies: + - role: ibm.mas_devops.ansible_version_check + diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml new file mode 100644 index 0000000000..e372442a89 --- /dev/null +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml @@ -0,0 +1,237 @@ +--- +# Configure AI Service properties in Manage encryption secret +# This task retrieves AI Service connection details and patches them into the Manage encryption secret +# ----------------------------------------------------------------------------- + +- name: "Step 1: Retrieve AI Service API key from secret" + block: + - name: "Get AI Service API key secret" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "aiservice-{{ aiservice_instance_id }}-user----apikey-secret" + namespace: "{{ aiservice_namespace }}" + register: aiservice_apikey_secret_output + + - name: "Fail if AI Service API key secret not found" + fail: + msg: "Could not find AI Service API key secret: aiservice-{{ aiservice_instance_id }}-user----apikey-secret in namespace {{ aiservice_namespace }}" + when: aiservice_apikey_secret_output.resources | length == 0 + + - name: "Extract AI Service API key" + set_fact: + aiservice_api_key: "{{ aiservice_apikey_secret_output.resources[0].data.AIBROKER_APIKEY | b64decode }}" + + - name: "Verify API key was retrieved" + fail: + msg: "Could not retrieve AI Service API key from secret" + when: aiservice_api_key is not defined or aiservice_api_key == "" + + +# Step 2: Retrieve AI Service URL from aibroker route +# ----------------------------------------------------------------------------- +- name: "Step 2: Retrieve AI Service URL from aibroker route" + block: + - name: "Get aibroker route" + kubernetes.core.k8s_info: + api_version: route.openshift.io/v1 + kind: Route + name: aibroker + namespace: "{{ aiservice_namespace }}" + register: aibroker_route_output + + - name: "Fail if aibroker route not found" + fail: + msg: "Could not find aibroker route in namespace {{ aiservice_namespace }}" + when: aibroker_route_output.resources | length == 0 + + - name: "Extract aibroker host" + set_fact: + aibroker_host: "{{ aibroker_route_output.resources[0].spec.host }}" + + - name: "Construct AI Service URL" + set_fact: + aiservice_url: "https://{{ aibroker_host }}/ibm/aibroker/service/rest/api/v1" + + +# Step 3: Retrieve AI Service tenant ID from AIServiceTenant custom resource +# ----------------------------------------------------------------------------- +- name: "Step 3: Retrieve AI Service tenant ID from AIServiceTenant CR" + block: + - name: "Get AIServiceTenant custom resource" + kubernetes.core.k8s_info: + api_version: aiservice.ibm.com/v1 + kind: AIServiceTenant + namespace: "{{ aiservice_namespace }}" + register: aiservice_tenant_output + + - name: "Fail if AIServiceTenant not found" + fail: + msg: "Could not find AIServiceTenant custom resource in namespace {{ aiservice_namespace }}" + when: aiservice_tenant_output.resources | length == 0 + + - name: "Extract AI Service tenant ID from first resource" + set_fact: + aiservice_tenant_id: "{{ aiservice_tenant_output.resources[0].metadata.name }}" + + - name: "Verify tenant ID was retrieved" + fail: + msg: "Could not retrieve AI Service tenant ID from AIServiceTenant CR" + when: aiservice_tenant_id is not defined or aiservice_tenant_id == "" + + +# Step 4: Patch AI Service properties into Manage encryption secret +# ----------------------------------------------------------------------------- +- name: "Step 4: Patch AI Service properties into Manage encryption secret" + block: + - name: "Verify Manage encryption secret exists" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ manage_encryption_secret_name }}" + namespace: "{{ manage_namespace }}" + register: manage_secret_output + + - name: "Fail if Manage encryption secret not found" + fail: + msg: "Could not find Manage encryption secret: {{ manage_encryption_secret_name }} in namespace {{ manage_namespace }}" + when: manage_secret_output.resources | length == 0 + + + - name: "Encode AI Service properties to base64" + set_fact: + encoded_apikey: "{{ aiservice_api_key | b64encode }}" + encoded_url: "{{ aiservice_url | b64encode }}" + encoded_tenantid: "{{ aiservice_tenant_id | b64encode }}" + + - name: "Remove existing AI Service properties (if any)" + kubernetes.core.k8s_json_patch: + api_version: v1 + kind: Secret + name: "{{ manage_encryption_secret_name }}" + namespace: "{{ manage_namespace }}" + patch: + - op: remove + path: /data/mxe.int.aibrokerapikey + ignore_errors: true + + - name: "Remove existing AI Service URL property (if any)" + kubernetes.core.k8s_json_patch: + api_version: v1 + kind: Secret + name: "{{ manage_encryption_secret_name }}" + namespace: "{{ manage_namespace }}" + patch: + - op: remove + path: /data/mxe.int.aibrokerapiurl + ignore_errors: true + + - name: "Remove existing AI Service tenant ID property (if any)" + kubernetes.core.k8s_json_patch: + api_version: v1 + kind: Secret + name: "{{ manage_encryption_secret_name }}" + namespace: "{{ manage_namespace }}" + patch: + - op: remove + path: /data/mxe.int.aibrokertenantid + ignore_errors: true + + - name: "Add AI Service properties to secret" + kubernetes.core.k8s_json_patch: + api_version: v1 + kind: Secret + name: "{{ manage_encryption_secret_name }}" + namespace: "{{ manage_namespace }}" + patch: + - op: add + path: /data/mxe.int.aibrokerapikey + value: "{{ encoded_apikey }}" + - op: add + path: /data/mxe.int.aibrokerapiurl + value: "{{ encoded_url }}" + - op: add + path: /data/mxe.int.aibrokertenantid + value: "{{ encoded_tenantid }}" + + +# Step 5: Verify the secret was updated +# ----------------------------------------------------------------------------- +- name: "Step 5: Verify AI Service properties in secret" + block: + - name: "Get updated secret" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ manage_encryption_secret_name }}" + namespace: "{{ manage_namespace }}" + register: updated_secret_output + + - name: "Verify mxe.int.aibrokerapikey is present" + assert: + that: "'mxe.int.aibrokerapikey' in updated_secret_output.resources[0].data" + success_msg: "Verified: mxe.int.aibrokerapikey is present in secret" + fail_msg: "Failed: mxe.int.aibrokerapikey is not present in secret" + + - name: "Verify mxe.int.aibrokerapiurl is present" + assert: + that: "'mxe.int.aibrokerapiurl' in updated_secret_output.resources[0].data" + success_msg: "Verified: mxe.int.aibrokerapiurl is present in secret" + fail_msg: "Failed: mxe.int.aibrokerapiurl is not present in secret" + + - name: "Verify mxe.int.aibrokertenantid is present" + assert: + that: "'mxe.int.aibrokertenantid' in updated_secret_output.resources[0].data" + success_msg: "Verified: mxe.int.aibrokertenantid is present in secret" + fail_msg: "Failed: mxe.int.aibrokertenantid is not present in secret" + +# Step 6: Import AI Service TLS certificate into Manage truststore +# ----------------------------------------------------------------------------- +- name: "Step 6: Import AI Service TLS certificate into Manage" + block: + - name: "Get AI Service TLS certificate from secret" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ aiservice_instance_id }}-public-aibroker-tls" + namespace: "{{ aiservice_namespace }}" + register: aiservice_tls_secret_output + + - name: "Fail if AI Service TLS secret not found" + fail: + msg: "Could not find AI Service TLS secret: {{ aiservice_instance_id }}-public-aibroker-tls in namespace {{ aiservice_namespace }}" + when: aiservice_tls_secret_output.resources | length == 0 + + - name: "Extract TLS certificate from secret" + set_fact: + aiservice_tls_cert: "{{ aiservice_tls_secret_output.resources[0].data['ca.crt'] | b64decode }}" + + - name: "Verify TLS certificate was retrieved" + fail: + msg: "Could not retrieve AI Service TLS certificate from secret" + when: aiservice_tls_cert is not defined or aiservice_tls_cert == "" + + - name: "Build certificate entry for ManageWorkspace" + set_fact: + aiservice_cert_entry: + - alias: "aiservice-{{ aiservice_instance_id }}-tls1" + crt: "{{ aiservice_tls_cert }}" + + - name: "Import AI Service TLS certificate into ManageWorkspace" + kubernetes.core.k8s_json_patch: + api_version: apps.mas.ibm.com/v1 + kind: ManageWorkspace + name: "{{ mas_instance_id }}-{{ mas_workspace_id }}" + namespace: "mas-{{ mas_instance_id }}-manage" + patch: + - op: add + path: /spec/settings/deployment/importedCerts + value: "{{ aiservice_cert_entry }}" + +- name: "AI Service configuration completed successfully" + debug: + msg: + - "AI Service properties configured in Manage encryption secret successfully" + - "AI Service TLS certificate imported into Manage truststore" + - "Note: Manage will automatically restart to apply these changes" + diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml new file mode 100644 index 0000000000..de908aeb64 --- /dev/null +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml @@ -0,0 +1,76 @@ +--- +# Assertions: preliminary validations +# ----------------------------------------------------------------------------- + +# Assertion: mas_instance_id is required +- name: "Fail if mas_instance_id is not provided" + assert: + that: mas_instance_id is defined and mas_instance_id != "" + fail_msg: "mas_instance_id property is required" + +# Assertion: mas_workspace_id is required +- name: "Fail if mas_workspace_id is not provided" + assert: + that: mas_workspace_id is defined and mas_workspace_id != "" + fail_msg: "mas_workspace_id property is required" + +# Assertion: aiservice_instance_id is required +- name: "Fail if aiservice_instance_id is not provided" + assert: + that: aiservice_instance_id is defined and aiservice_instance_id != "" + fail_msg: "aiservice_instance_id property is required" + +# Assertion: mas_app_id must be 'manage' +- name: "Fail if mas_app_id is not 'manage'" + assert: + that: + - mas_app_id is defined and mas_app_id != "" + - mas_app_id == 'manage' + fail_msg: "mas_app_id property is required and must be set to 'manage'" + +# Check CM: if AI Service is already configured via internal config map +# ----------------------------------------------------------------------------- +- name: "Check CM: if AI Service is already configured via internal config map" + kubernetes.core.k8s_info: + api_version: v1 + kind: ConfigMap + name: "{{ mas_instance_id }}-{{ mas_workspace_id }}-manage-aiservice-configmap" + namespace: "{{ manage_namespace }}" + register: manage_aiservice_cm_output + +- set_fact: + mas_manage_aiservice_configured: "{{ manage_aiservice_cm_output.resources | length > 0 }}" + mas_manage_aiservice_version: "{{ manage_aiservice_cm_output.resources[0].data.aiservice_instance_id | default('', true) if manage_aiservice_cm_output.resources | length > 0 else '' }}" + +- name: Debug + debug: + msg: + - "mas_instance_id ................................... {{ mas_instance_id }}" + - "mas_workspace_id .................................. {{ mas_workspace_id }}" + - "mas_app_id ........................................ {{ mas_app_id }}" + - "" + - "aiservice_instance_id ............................. {{ aiservice_instance_id }}" + - "aiservice_namespace ............................... {{ aiservice_namespace }}" + - "" + - "manage_namespace .................................. {{ manage_namespace }}" + - "manage_encryption_secret_name ..................... {{ manage_encryption_secret_name }}" + - "" + - "mas_manage_aiservice_configured ................... {{ mas_manage_aiservice_configured }}" + - "mas_manage_aiservice_version (existing) ........... {{ mas_manage_aiservice_version }}" + - "" + - "{{ (mas_manage_aiservice_version == aiservice_instance_id) | ternary('AI Service is already configured for this instance, skipping configuration','AI Service is not configured or instance has changed, proceeding with configuration...') }}" + +# Configure AI Service properties +# ----------------------------------------------------------------------------- +- name: "Configure AI Service properties in Manage" + include_tasks: "configure.yml" + when: mas_manage_aiservice_version != aiservice_instance_id # only configure when AI Service is not setup yet or instance changed + +# Set CM: config map to track AI Service configuration (keep idempotency of ansible role) +# ----------------------------------------------------------------------------- +- name: "Set CM: config map to track AI Service configuration" + kubernetes.core.k8s: + apply: yes + template: "templates/configmap.yml.j2" + when: mas_manage_aiservice_version != aiservice_instance_id # only configure when AI Service is not setup yet or instance changed + diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 b/ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 new file mode 100644 index 0000000000..45072606ec --- /dev/null +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ mas_instance_id }}-{{ mas_workspace_id }}-manage-aiservice-configmap" + namespace: "{{ manage_namespace }}" + labels: + mas.ibm.com/instanceId: "{{ mas_instance_id }}" + mas.ibm.com/workspaceId: "{{ mas_workspace_id }}" + mas.ibm.com/applicationId: "{{ mas_app_id }}" +data: + aiservice_instance_id: "{{ aiservice_instance_id }}" + aiservice_namespace: "{{ aiservice_namespace }}" + configured_at: "{{ ansible_date_time.iso8601 }}" From c291bfae3709efef4b76648095de516298d66950 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Fri, 21 Nov 2025 09:40:04 +0530 Subject: [PATCH 02/27] [minor] finalize changes --- build/bin/copy-role-docs.sh | 1 + .../roles/suite_manage_aiservice_config/README.md | 8 +++----- mkdocs.yml | 1 + 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/bin/copy-role-docs.sh b/build/bin/copy-role-docs.sh index b6721f1bf0..1729fb5496 100644 --- a/build/bin/copy-role-docs.sh +++ b/build/bin/copy-role-docs.sh @@ -86,6 +86,7 @@ copyDoc suite_install copyDoc suite_manage_bim_config copyDoc suite_manage_birt_report_config copyDoc suite_manage_customer_files_config +copyDoc suite_manage_aiservice_config copyDoc suite_manage_attachments_config copyDoc suite_manage_imagestitching_config copyDoc suite_manage_import_certs_config diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md b/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md index 874497be0b..5c84c07835 100644 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md @@ -4,7 +4,8 @@ suite_manage_aiservice_config This role configures AI Service integration for Maximo Manage by: 1. Retrieving AI Service connection details (API key, URL, tenant ID) 2. Patching these properties into the Manage encryption secret -3. Triggering Manage restart to apply the configuration +3. Importing AI Service TLS certificate into Manage truststore +4. Triggering Manage restart to apply the configuration Role Variables ------------------------------------------------------------------------------- @@ -12,13 +13,12 @@ Role Variables ### Required Variables - `mas_instance_id`: MAS instance ID -- `mas_workspace_id`: MAS workspace ID +- `mas_workspace_id`: MAS workspace ID - `aiservice_instance_id`: AI Service instance ID ### Optional Variables - `mas_app_id`: Application ID (default: `manage`) -- `mas_manage_aiservice_configuration_mode`: Configuration mode (default: empty string) Example Playbook ------------------------------------------------------------------------------- @@ -29,7 +29,6 @@ Example Playbook mas_instance_id: "mymas" mas_workspace_id: "masdev" aiservice_instance_id: "mymas" - mas_manage_aiservice_configuration_mode: "aiservice" roles: - ibm.mas_devops.suite_manage_aiservice_config ``` @@ -41,7 +40,6 @@ Environment Variables - `MAS_WORKSPACE_ID`: MAS workspace ID - `AISERVICE_INSTANCE_ID`: AI Service instance ID - `MAS_APP_ID`: Application ID (default: `manage`) -- `MAS_MANAGE_AISERVICE_CONFIGURATION_MODE`: Configuration mode License ------------------------------------------------------------------------------- diff --git a/mkdocs.yml b/mkdocs.yml index c5f6fb7ae5..181bf5ba7c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -87,6 +87,7 @@ nav: - "suite_db2_setup_for_manage": roles/suite_db2_setup_for_manage.md - "suite_dns": roles/suite_dns.md - "suite_install": roles/suite_install.md + - "suite_manage_aiservice_config": roles/suite_manage_aiservice_config.md - "suite_manage_attachments_config": roles/suite_manage_attachments_config.md - "suite_manage_birt_report_config": roles/suite_manage_birt_report_config.md - "suite_manage_bim_config": roles/suite_manage_bim_config.md From 644568c3a48e6472b3df02b2bb1cb61db12d77f4 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Thu, 4 Dec 2025 16:49:19 +0530 Subject: [PATCH 03/27] [minor] remove unwanted var --- .../roles/suite_app_config/tasks/manage/post-config/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml index 2d84d76f60..36e9dc334a 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml @@ -49,6 +49,5 @@ include_role: name: ibm.mas_devops.suite_manage_aiservice_config when: - - mas_manage_attachment_configuration_mode == "aiservice" - aiservice_instance_id is defined - aiservice_instance_id != "" From 608692bdacf41132ea531442b220630cbe1d9757 Mon Sep 17 00:00:00 2001 From: Bhautik Vala Date: Thu, 4 Dec 2025 19:19:03 +0530 Subject: [PATCH 04/27] [patch] Add aiservice_instance_id in suite_app_config role's default vars --- ibm/mas_devops/roles/suite_app_config/defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/defaults/main.yml b/ibm/mas_devops/roles/suite_app_config/defaults/main.yml index 6c68fc3d3b..552a7f2527 100644 --- a/ibm/mas_devops/roles/suite_app_config/defaults/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/defaults/main.yml @@ -9,7 +9,7 @@ custom_labels: "{{ lookup('env', 'CUSTOM_LABELS') | default(None, true) | string mas_instance_id: "{{ lookup('env', 'MAS_INSTANCE_ID') }}" mas_workspace_id: "{{ lookup('env', 'MAS_WORKSPACE_ID') }}" mas_config_dir: "{{ lookup('env', 'MAS_CONFIG_DIR') }}" - +aiservice_instance_id: "{{ lookup('env', 'AISERVICE_INSTANCE_ID') }}" # 3. MAS application configuration # ----------------------------------------------------------------------------- From bd33d0125f3b8a18824c1686a72ddd210be05870 Mon Sep 17 00:00:00 2001 From: Bhautik Vala Date: Mon, 8 Dec 2025 11:14:40 +0530 Subject: [PATCH 05/27] [patch] Change Namespace for jdbcCfg when db2-aiservice getting installed --- ibm/mas_devops/roles/db2/templates/suite_jdbccfg.yml.j2 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ibm/mas_devops/roles/db2/templates/suite_jdbccfg.yml.j2 b/ibm/mas_devops/roles/db2/templates/suite_jdbccfg.yml.j2 index 7faa0b47d0..508bb94150 100644 --- a/ibm/mas_devops/roles/db2/templates/suite_jdbccfg.yml.j2 +++ b/ibm/mas_devops/roles/db2/templates/suite_jdbccfg.yml.j2 @@ -4,7 +4,11 @@ kind: Secret type: Opaque metadata: name: "jdbc-{{ db2_instance_name | lower }}-credentials" +{% if db2_instance_name.startswith('aiservice') %} + namespace: "aiservice-{{ mas_instance_id }}" +{% else %} namespace: "mas-{{ mas_instance_id }}-core" +{% endif %} {% if custom_labels is defined and custom_labels.items() %} labels: {% for key, value in custom_labels.items() %} @@ -19,7 +23,11 @@ apiVersion: config.mas.ibm.com/v1 kind: JdbcCfg metadata: name: "{{ suite_jdbccfg_name }}" +{% if db2_instance_name.startswith('aiservice') %} + namespace: "aiservice-{{ mas_instance_id }}" +{% else %} namespace: "mas-{{ mas_instance_id }}-core" +{% endif %} labels: {{ suite_jdbccfg_labels }} spec: displayName: "{{ suite_jdbccfg_name }}" From ed93e9fa2be6971b7a191c55a06a44e126b335f4 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 10 Dec 2025 16:20:56 +0530 Subject: [PATCH 06/27] [minor] added steps to verify AI Service health --- .../suite_manage_aiservice_config/README.md | 2 +- .../tasks/configure.yml | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md b/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md index 5c84c07835..3eb7654df5 100644 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md @@ -5,7 +5,7 @@ This role configures AI Service integration for Maximo Manage by: 1. Retrieving AI Service connection details (API key, URL, tenant ID) 2. Patching these properties into the Manage encryption secret 3. Importing AI Service TLS certificate into Manage truststore -4. Triggering Manage restart to apply the configuration +4. Verifying AI Service health and connectivity Role Variables ------------------------------------------------------------------------------- diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml index e372442a89..7c0d9c112d 100644 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml @@ -228,10 +228,80 @@ path: /spec/settings/deployment/importedCerts value: "{{ aiservice_cert_entry }}" +# Step 7: Verify AI Service health +# ----------------------------------------------------------------------------- +- name: "Step 7: Verify AI Service is running and healthy" + block: + - name: "Get aibroker route host" + kubernetes.core.k8s_info: + api_version: route.openshift.io/v1 + kind: Route + name: aibroker + namespace: "{{ aiservice_namespace }}" + register: aibroker_route_output + + - name: "Fail if aibroker route not found" + fail: + msg: "Could not find aibroker route in namespace {{ aiservice_namespace }}" + when: aibroker_route_output.resources | length == 0 + + - name: "Extract aibroker host" + set_fact: + aibroker_host: "{{ aibroker_route_output.resources[0].spec.host }}" + + - name: "Set AI Service health URL" + set_fact: + aiservice_health_url: "https://{{ aibroker_host }}/ibm/aibroker/service/rest/api/v1/health" + + - name: "Check AI Service health endpoint" + uri: + url: "{{ aiservice_health_url }}" + method: GET + validate_certs: false + return_content: true + status_code: [200, 503] + register: aiservice_health_response + retries: 5 + delay: 10 + until: + - aiservice_health_response.status == 200 + - aiservice_health_response.json is defined + failed_when: false + + - name: "Fail if health endpoint never returned 200" + fail: + msg: "AI Service health endpoint failed to return HTTP 200 after 5 attempts. Last status: {{ aiservice_health_response.status }}" + when: aiservice_health_response.status != 200 + + - name: "Parse AI Service health response" + set_fact: + aiservice_kmodel_status: "{{ aiservice_health_response.json.kmodel | default('unknown') }}" + aiservice_healthy_status: "{{ aiservice_health_response.json.healthy | default(false) }}" + + - name: "Display AI Service health status" + debug: + msg: + - "AI Service Health Check:" + - " URL: {{ aiservice_health_url }}" + - " kmodel: {{ aiservice_kmodel_status }}" + - " healthy: {{ aiservice_healthy_status }}" + + - name: "Verify AI Service is fully healthy" + assert: + that: + - aiservice_kmodel_status == 'running' + - aiservice_healthy_status == true + success_msg: "AI Service is running and healthy" + fail_msg: | + AI Service is not fully healthy: + - kmodel: {{ aiservice_kmodel_status }} (expected: running) + - healthy: {{ aiservice_healthy_status }} (expected: true) + - name: "AI Service configuration completed successfully" debug: msg: - "AI Service properties configured in Manage encryption secret successfully" - "AI Service TLS certificate imported into Manage truststore" + - "AI Service health verified - service is running and healthy" - "Note: Manage will automatically restart to apply these changes" From 89a4784dc37c278293200801eab24306ffeff73f Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 10 Dec 2025 16:30:20 +0530 Subject: [PATCH 07/27] [patch] fix lint errors --- ibm/mas_devops/meta/runtime.yml | 1 - .../roles/suite_manage_aiservice_config/defaults/main.yml | 1 - .../roles/suite_manage_aiservice_config/meta/main.yml | 1 - .../roles/suite_manage_aiservice_config/tasks/configure.yml | 3 +-- .../roles/suite_manage_aiservice_config/tasks/main.yml | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ibm/mas_devops/meta/runtime.yml b/ibm/mas_devops/meta/runtime.yml index 3ada052995..8d4c46761c 100644 --- a/ibm/mas_devops/meta/runtime.yml +++ b/ibm/mas_devops/meta/runtime.yml @@ -13,4 +13,3 @@ action_groups: - verify_workloads - wait_for_app_ready - wait_for_conditions - diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml index e0a41fc4ef..ecc1a58ac9 100644 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml @@ -16,4 +16,3 @@ manage_namespace: "mas-{{ mas_instance_id }}-{{ mas_app_id }}" # Manage encryption secret name # This is the secret where AI Service properties will be stored manage_encryption_secret_name: "{{ mas_workspace_id }}-manage-encryptionsecret" - diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml index 2cfcdafd7e..7ec0e66351 100644 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml @@ -9,7 +9,6 @@ galaxy_info: - name: EL versions: - "8" - dependencies: - role: ibm.mas_devops.ansible_version_check diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml index 7c0d9c112d..e91afd260f 100644 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml @@ -267,7 +267,7 @@ - aiservice_health_response.status == 200 - aiservice_health_response.json is defined failed_when: false - + - name: "Fail if health endpoint never returned 200" fail: msg: "AI Service health endpoint failed to return HTTP 200 after 5 attempts. Last status: {{ aiservice_health_response.status }}" @@ -304,4 +304,3 @@ - "AI Service TLS certificate imported into Manage truststore" - "AI Service health verified - service is running and healthy" - "Note: Manage will automatically restart to apply these changes" - diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml index de908aeb64..da8a8e34aa 100644 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml +++ b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml @@ -73,4 +73,3 @@ apply: yes template: "templates/configmap.yml.j2" when: mas_manage_aiservice_version != aiservice_instance_id # only configure when AI Service is not setup yet or instance changed - From 1c16e3a81cc1c8a09f1257d046d1bd55e376f7d4 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Mon, 15 Dec 2025 11:05:06 +0530 Subject: [PATCH 08/27] [minor] add ai-service configuration in pre-config --- .../roles/suite_app_config/defaults/main.yml | 4 + .../tasks/manage/post-config/main.yml | 8 - .../tasks/manage/pre-config/main.yml | 20 +- .../pre-config/setup-aiservice-config.yml | 176 ++++++++++++++++++ .../manage/encryption-secrets.yml.j2 | 14 +- .../vars/defaultspecs/manage.yml | 1 + 6 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml diff --git a/ibm/mas_devops/roles/suite_app_config/defaults/main.yml b/ibm/mas_devops/roles/suite_app_config/defaults/main.yml index 552a7f2527..71e1b20619 100644 --- a/ibm/mas_devops/roles/suite_app_config/defaults/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/defaults/main.yml @@ -9,7 +9,11 @@ custom_labels: "{{ lookup('env', 'CUSTOM_LABELS') | default(None, true) | string mas_instance_id: "{{ lookup('env', 'MAS_INSTANCE_ID') }}" mas_workspace_id: "{{ lookup('env', 'MAS_WORKSPACE_ID') }}" mas_config_dir: "{{ lookup('env', 'MAS_CONFIG_DIR') }}" + +# AI Service configuration +# ----------------------------------------------------------------------------- aiservice_instance_id: "{{ lookup('env', 'AISERVICE_INSTANCE_ID') }}" +aiservice_tenant_id: "{{ lookup('env', 'AISERVICE_TENANT_ID') }}" # 3. MAS application configuration # ----------------------------------------------------------------------------- diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml index cbbc39ed1a..f18c4f1ad1 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml @@ -43,11 +43,3 @@ when: - mas_manage_attachment_configuration_mode in ["db", "cr"] - mas_manage_attachments_provider in ["filestorage", "ibm", "aws"] - -# Manage post-configuration: AI Service -- name: "Run Manage post-configuration: Set up AI Service integration" - include_role: - name: ibm.mas_devops.suite_manage_aiservice_config - when: - - aiservice_instance_id is defined - - aiservice_instance_id != "" diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml index a385610443..e322acbf69 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml @@ -33,11 +33,19 @@ - mas_app_settings_customization_archive_url | length > 0 include_tasks: "tasks/manage/pre-config/setup-custom-archive.yml" -# Manage pre-configuration: Database encryption setup -- name: "Run Manage specific pre-configuration: Set database encryption keys" +# Manage pre-configuration: AI Service integration setup +- name: "Run Manage specific pre-configuration: Set up AI Service integration" + when: + - aiservice_instance_id is defined + - aiservice_instance_id != "" + include_tasks: "tasks/manage/pre-config/setup-aiservice-config.yml" + +# Manage pre-configuration: Database encryption and AI Service secrets setup +- name: "Run Manage specific pre-configuration: Set database encryption keys and AI Service secrets" when: > - mas_app_settings_crypto_key is defined and mas_app_settings_crypto_key != '' and - mas_app_settings_cryptox_key is defined and mas_app_settings_cryptox_key != '' or - mas_app_settings_old_crypto_key is defined and mas_app_settings_old_crypto_key != '' and - mas_app_settings_old_cryptox_key is defined and mas_app_settings_old_cryptox_key != '' + (mas_app_settings_crypto_key is defined and mas_app_settings_crypto_key != '' and + mas_app_settings_cryptox_key is defined and mas_app_settings_cryptox_key != '') or + (mas_app_settings_old_crypto_key is defined and mas_app_settings_old_crypto_key != '' and + mas_app_settings_old_cryptox_key is defined and mas_app_settings_old_cryptox_key != '') or + (aiservice_api_key is defined and aiservice_api_key != '') include_tasks: "tasks/manage/pre-config/setup-encryption-secret.yml" diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml new file mode 100644 index 0000000000..7c69dfd6c3 --- /dev/null +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -0,0 +1,176 @@ +--- +# Manage specific steps to configure AI Service integration +# This retrieves AI Service connection details and sets them as facts +# to be included in the Manage encryption secret +# ------------------------------------------------------------------------ + +# Set AI Service namespace +- set_fact: + aiservice_namespace: "aiservice-{{ aiservice_instance_id }}" + +# Step 1: Retrieve AI Service tenant ID from AIServiceTenant custom resource +# ------------------------------------------------------------------------ +- name: "Step 1: Retrieve AI Service tenant ID from AIServiceTenant CR if not explicitly provided" + when: aiservice_tenant_id is not defined or aiservice_tenant_id == "" + block: + - name: "List all AIServiceTenant CRs in AI Service namespace" + kubernetes.core.k8s_info: + api_version: aiservice.ibm.com/v1 + kind: AIServiceTenant + namespace: "{{ aiservice_namespace }}" + register: aiservice_tenants_list + + - name: "Fail if no AIServiceTenant CRs found" + fail: + msg: "No AIServiceTenant CRs found in namespace '{{ aiservice_namespace }}'. Please ensure AI Service is properly installed." + when: + - aiservice_tenants_list.resources is not defined or aiservice_tenants_list.resources | length == 0 + + - name: "Extract first tenant name" + set_fact: + aiservice_tenant_id: "{{ aiservice_tenants_list.resources[0].metadata.name }}" + + - name: "Debug: AI Servicetenant ID" + debug: + msg: "AI Service tenant ID: {{ aiservice_tenant_id }}" + +# Step 2: Retrieve AI Service API key (tenant-specific) +# ------------------------------------------------------------------------ +- name: "Step 2: Lookup AI Service tenant API key secret" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ aiservice_tenant_id }}----apikey-secret" + namespace: "{{ aiservice_namespace }}" + register: aiservice_apikey_secret + +- name: "Fail if AI Service tenant API key secret not found" + fail: + msg: "AI Service tenant API key secret '{{ aiservice_tenant_id }}----apikey-secret' not found in namespace '{{ aiservice_namespace }}'" + when: + - aiservice_apikey_secret.resources is not defined or aiservice_apikey_secret.resources | length == 0 + +- name: "Extract AI Service API key" + set_fact: + aiservice_api_key: "{{ aiservice_apikey_secret.resources[0].data.AIBROKER_APIKEY | b64decode }}" + +- name: "Verify AI Service API key was retrieved" + fail: + msg: "Could not retrieve AI Service API key from secret" + when: aiservice_api_key is not defined or aiservice_api_key == "" + +# Step 3: Retrieve AI Service URL from aibroker route +# ------------------------------------------------------------------------ +- name: "Step 3: Retrieve AI Service URL from aibroker route" + kubernetes.core.k8s_info: + api_version: route.openshift.io/v1 + kind: Route + name: "aibroker" + namespace: "{{ aiservice_namespace }}" + register: aiservice_route + +- name: "Fail if aibroker route not found" + fail: + msg: "AI Service route 'aibroker' not found in namespace '{{ aiservice_namespace }}'" + when: + - aiservice_route.resources is not defined or aiservice_route.resources | length == 0 + +- name: "Extract AI Service URL" + set_fact: + aiservice_url: "https://{{ aiservice_route.resources[0].spec.host }}/ibm/aibroker/service/rest/api/v1" + +# Step 4: Retrieve AI Service TLS certificate for import +# ------------------------------------------------------------------------ +- name: "Step 4: Lookup AI Service TLS certificate secret" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ aiservice_instance_id }}-public-aibroker-tls" + namespace: "{{ aiservice_namespace }}" + register: aiservice_tls_secret + +- name: "Fail if AI Service TLS certificate secret not found" + fail: + msg: "AI Service TLS certificate secret '{{ aiservice_instance_id }}-public-aibroker-tls' not found in namespace '{{ aiservice_namespace }}'" + when: + - aiservice_tls_secret.resources is not defined or aiservice_tls_secret.resources | length == 0 + +- name: "Extract AI Service TLS certificate" + set_fact: + aiservice_tls_cert: "{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode }}" + +# Step 5: Set certificate import configuration +# ------------------------------------------------------------------------ +- name: "Step 5: Set AI Service certificate import configuration" + set_fact: + aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" + aiservice_cert_import: + alias: "aiservice-{{ aiservice_instance_id }}-tls1" + crt: "{{ aiservice_tls_cert }}" + +# Step 6: Verify AI Service is running and healthy +# ------------------------------------------------------------------------ +- name: "Step 6: Verify AI Service is running and healthy" + block: + - name: "Set AI Service health URL" + set_fact: + aiservice_health_url: "https://{{ aiservice_route.resources[0].spec.host }}/ibm/aibroker/service/rest/api/v1/health" + + - name: "Check AI Service health endpoint" + uri: + url: "{{ aiservice_health_url }}" + method: GET + validate_certs: false + return_content: true + status_code: [200, 503] + register: aiservice_health_response + retries: 5 + delay: 10 + until: + - aiservice_health_response.status == 200 + - aiservice_health_response.json is defined + failed_when: false + + - name: "Fail if health endpoint never returned 200" + fail: + msg: "AI Service health endpoint failed to return HTTP 200 after 5 attempts. Last status: {{ aiservice_health_response.status }}" + when: aiservice_health_response.status != 200 + + - name: "Parse AI Service health response" + set_fact: + aiservice_kmodel_status: "{{ aiservice_health_response.json.kmodel | default('unknown') }}" + aiservice_healthy_status: "{{ aiservice_health_response.json.healthy | default(false) }}" + + - name: "Display AI Service health status" + debug: + msg: + - "AI Service Health Check:" + - " URL: {{ aiservice_health_url }}" + - " kmodel: {{ aiservice_kmodel_status }}" + - " healthy: {{ aiservice_healthy_status }}" + + - name: "Verify AI Service is fully healthy" + assert: + that: + - aiservice_kmodel_status == 'running' + - aiservice_healthy_status == true + success_msg: "AI Service is running and healthy" + fail_msg: | + AI Service is not fully healthy: + - kmodel: {{ aiservice_kmodel_status }} (expected: running) + - healthy: {{ aiservice_healthy_status }} (expected: true) + +# Debug output +# ------------------------------------------------------------------------ +- name: "Debug AI Service configuration" + debug: + msg: + - "AI Service instance ID ............................ {{ aiservice_instance_id }}" + - "AI Service tenant ID .............................. {{ aiservice_tenant_id }}" + - "AI Service namespace ............................... {{ aiservice_namespace }}" + - "AI Service URL ..................................... {{ aiservice_url }}" + - "AI Service certificate alias ....................... {{ aiservice_cert_alias }}" + - "AI Service API key retrieved ....................... Yes" + - "AI Service TLS certificate retrieved ............... Yes" + - "AI Service health status ........................... {{ aiservice_kmodel_status }} / {{ aiservice_healthy_status }}" + - "MAS instance ID .................................... {{ mas_instance_id }}" diff --git a/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 b/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 index e35fd2d13d..2fb75d1f56 100644 --- a/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 +++ b/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 @@ -1,5 +1,6 @@ -# secret to define manage database encryption settings -# https://www.ibm.com/docs/en/mas-cd/continuous-delivery?topic=encryption-database-scenarios +# Secret to define Manage database encryption settings and AI Service integration properties +# Database encryption: https://www.ibm.com/docs/en/mas-cd/continuous-delivery?topic=encryption-database-scenarios +# AI Service properties: mxe.int.aibrokerapikey, mxe.int.aibrokerapiurl, mxe.int.aibrokertenantid --- kind: Secret apiVersion: v1 @@ -21,3 +22,12 @@ stringData: MXE_SECURITY_OLD_CRYPTO_KEY: {{ mas_app_settings_old_crypto_key }} MXE_SECURITY_OLD_CRYPTOX_KEY: {{ mas_app_settings_old_cryptox_key }} {% endif %} +{% if aiservice_api_key is defined and aiservice_api_key !='' %} + mxe.int.aibrokerapikey: {{ aiservice_api_key }} +{% endif %} +{% if aiservice_url is defined and aiservice_url !='' %} + mxe.int.aibrokerapiurl: {{ aiservice_url }} +{% endif %} +{% if aiservice_tenant_id is defined and aiservice_tenant_id !='' %} + mxe.int.aibrokertenantid: {{ aiservice_tenant_id }} +{% endif %} diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index 6ea79d2329..b92155e8ef 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,6 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" + importedCerts: "{{ [aiservice_cert_import] if (aiservice_cert_import is defined) else [] }}" languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}" From c5d3c3b5691d43d53c5e7742678c6d5266c9b998 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Mon, 15 Dec 2025 12:51:50 +0530 Subject: [PATCH 09/27] [patch] Use pre-config/ remove new role which is not required --- build/bin/copy-role-docs.sh | 1 - .../tasks/manage/post-config/main.yml | 1 - .../suite_manage_aiservice_config/README.md | 46 --- .../defaults/main.yml | 18 -- .../meta/main.yml | 14 - .../tasks/configure.yml | 306 ------------------ .../tasks/main.yml | 75 ----- .../templates/configmap.yml.j2 | 14 - mkdocs.yml | 1 - 9 files changed, 476 deletions(-) delete mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/README.md delete mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml delete mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml delete mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml delete mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml delete mode 100644 ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 diff --git a/build/bin/copy-role-docs.sh b/build/bin/copy-role-docs.sh index 4beb95b854..274c4d8678 100644 --- a/build/bin/copy-role-docs.sh +++ b/build/bin/copy-role-docs.sh @@ -82,7 +82,6 @@ copyDoc suite_install copyDoc suite_manage_bim_config copyDoc suite_manage_birt_report_config copyDoc suite_manage_customer_files_config -copyDoc suite_manage_aiservice_config copyDoc suite_manage_attachments_config copyDoc suite_manage_imagestitching_config copyDoc suite_manage_import_certs_config diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml index f18c4f1ad1..e3b9f69c82 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/post-config/main.yml @@ -14,7 +14,6 @@ - "COS Instance Name ...................... {{ cos_instance_name }}" - "COS Bucket Name ........................ {{ cos_bucket_name }}" - "IBM Cloud Resource Group ............... {{ ibmcloud_resourcegroup }}" - - "AI Service Instance ID ................. {{ aiservice_instance_id | default('Not configured', true) }}" # Manage post-configuration: Image stitching - name: "Run Manage post-configuration: Set up image stitching" diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md b/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md deleted file mode 100644 index 3eb7654df5..0000000000 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/README.md +++ /dev/null @@ -1,46 +0,0 @@ -suite_manage_aiservice_config -=============================================================================== - -This role configures AI Service integration for Maximo Manage by: -1. Retrieving AI Service connection details (API key, URL, tenant ID) -2. Patching these properties into the Manage encryption secret -3. Importing AI Service TLS certificate into Manage truststore -4. Verifying AI Service health and connectivity - -Role Variables -------------------------------------------------------------------------------- - -### Required Variables - -- `mas_instance_id`: MAS instance ID -- `mas_workspace_id`: MAS workspace ID -- `aiservice_instance_id`: AI Service instance ID - -### Optional Variables - -- `mas_app_id`: Application ID (default: `manage`) - -Example Playbook -------------------------------------------------------------------------------- - -```yaml -- hosts: localhost - vars: - mas_instance_id: "mymas" - mas_workspace_id: "masdev" - aiservice_instance_id: "mymas" - roles: - - ibm.mas_devops.suite_manage_aiservice_config -``` - -Environment Variables -------------------------------------------------------------------------------- - -- `MAS_INSTANCE_ID`: MAS instance ID -- `MAS_WORKSPACE_ID`: MAS workspace ID -- `AISERVICE_INSTANCE_ID`: AI Service instance ID -- `MAS_APP_ID`: Application ID (default: `manage`) - -License -------------------------------------------------------------------------------- -EPL-2.0 \ No newline at end of file diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml deleted file mode 100644 index ecc1a58ac9..0000000000 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/defaults/main.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -# The following MAS information is needed to lookup the right Manage app instance -mas_instance_id: "{{ lookup('env', 'MAS_INSTANCE_ID') }}" -mas_workspace_id: "{{ lookup('env', 'MAS_WORKSPACE_ID') | default('masdev', true) }}" -mas_app_id: "{{ lookup('env', 'MAS_APP_ID') | default('manage', true) }}" - -# AI Service instance information -aiservice_instance_id: "{{ lookup('env', 'AISERVICE_INSTANCE_ID') }}" - -# AI Service namespace -aiservice_namespace: "aiservice-{{ aiservice_instance_id }}" - -# Manage namespace -manage_namespace: "mas-{{ mas_instance_id }}-{{ mas_app_id }}" - -# Manage encryption secret name -# This is the secret where AI Service properties will be stored -manage_encryption_secret_name: "{{ mas_workspace_id }}-manage-encryptionsecret" diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml deleted file mode 100644 index 7ec0e66351..0000000000 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/meta/main.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -galaxy_info: - author: Divyesh Khokhar(@Divyesh-Khokhar) - description: Configure AI Service integration for Maximo Manage - company: IBM - license: EPL-2.0 - min_ansible_version: "2.10" - platforms: - - name: EL - versions: - - "8" -dependencies: - - role: ibm.mas_devops.ansible_version_check - diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml deleted file mode 100644 index e91afd260f..0000000000 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/configure.yml +++ /dev/null @@ -1,306 +0,0 @@ ---- -# Configure AI Service properties in Manage encryption secret -# This task retrieves AI Service connection details and patches them into the Manage encryption secret -# ----------------------------------------------------------------------------- - -- name: "Step 1: Retrieve AI Service API key from secret" - block: - - name: "Get AI Service API key secret" - kubernetes.core.k8s_info: - api_version: v1 - kind: Secret - name: "aiservice-{{ aiservice_instance_id }}-user----apikey-secret" - namespace: "{{ aiservice_namespace }}" - register: aiservice_apikey_secret_output - - - name: "Fail if AI Service API key secret not found" - fail: - msg: "Could not find AI Service API key secret: aiservice-{{ aiservice_instance_id }}-user----apikey-secret in namespace {{ aiservice_namespace }}" - when: aiservice_apikey_secret_output.resources | length == 0 - - - name: "Extract AI Service API key" - set_fact: - aiservice_api_key: "{{ aiservice_apikey_secret_output.resources[0].data.AIBROKER_APIKEY | b64decode }}" - - - name: "Verify API key was retrieved" - fail: - msg: "Could not retrieve AI Service API key from secret" - when: aiservice_api_key is not defined or aiservice_api_key == "" - - -# Step 2: Retrieve AI Service URL from aibroker route -# ----------------------------------------------------------------------------- -- name: "Step 2: Retrieve AI Service URL from aibroker route" - block: - - name: "Get aibroker route" - kubernetes.core.k8s_info: - api_version: route.openshift.io/v1 - kind: Route - name: aibroker - namespace: "{{ aiservice_namespace }}" - register: aibroker_route_output - - - name: "Fail if aibroker route not found" - fail: - msg: "Could not find aibroker route in namespace {{ aiservice_namespace }}" - when: aibroker_route_output.resources | length == 0 - - - name: "Extract aibroker host" - set_fact: - aibroker_host: "{{ aibroker_route_output.resources[0].spec.host }}" - - - name: "Construct AI Service URL" - set_fact: - aiservice_url: "https://{{ aibroker_host }}/ibm/aibroker/service/rest/api/v1" - - -# Step 3: Retrieve AI Service tenant ID from AIServiceTenant custom resource -# ----------------------------------------------------------------------------- -- name: "Step 3: Retrieve AI Service tenant ID from AIServiceTenant CR" - block: - - name: "Get AIServiceTenant custom resource" - kubernetes.core.k8s_info: - api_version: aiservice.ibm.com/v1 - kind: AIServiceTenant - namespace: "{{ aiservice_namespace }}" - register: aiservice_tenant_output - - - name: "Fail if AIServiceTenant not found" - fail: - msg: "Could not find AIServiceTenant custom resource in namespace {{ aiservice_namespace }}" - when: aiservice_tenant_output.resources | length == 0 - - - name: "Extract AI Service tenant ID from first resource" - set_fact: - aiservice_tenant_id: "{{ aiservice_tenant_output.resources[0].metadata.name }}" - - - name: "Verify tenant ID was retrieved" - fail: - msg: "Could not retrieve AI Service tenant ID from AIServiceTenant CR" - when: aiservice_tenant_id is not defined or aiservice_tenant_id == "" - - -# Step 4: Patch AI Service properties into Manage encryption secret -# ----------------------------------------------------------------------------- -- name: "Step 4: Patch AI Service properties into Manage encryption secret" - block: - - name: "Verify Manage encryption secret exists" - kubernetes.core.k8s_info: - api_version: v1 - kind: Secret - name: "{{ manage_encryption_secret_name }}" - namespace: "{{ manage_namespace }}" - register: manage_secret_output - - - name: "Fail if Manage encryption secret not found" - fail: - msg: "Could not find Manage encryption secret: {{ manage_encryption_secret_name }} in namespace {{ manage_namespace }}" - when: manage_secret_output.resources | length == 0 - - - - name: "Encode AI Service properties to base64" - set_fact: - encoded_apikey: "{{ aiservice_api_key | b64encode }}" - encoded_url: "{{ aiservice_url | b64encode }}" - encoded_tenantid: "{{ aiservice_tenant_id | b64encode }}" - - - name: "Remove existing AI Service properties (if any)" - kubernetes.core.k8s_json_patch: - api_version: v1 - kind: Secret - name: "{{ manage_encryption_secret_name }}" - namespace: "{{ manage_namespace }}" - patch: - - op: remove - path: /data/mxe.int.aibrokerapikey - ignore_errors: true - - - name: "Remove existing AI Service URL property (if any)" - kubernetes.core.k8s_json_patch: - api_version: v1 - kind: Secret - name: "{{ manage_encryption_secret_name }}" - namespace: "{{ manage_namespace }}" - patch: - - op: remove - path: /data/mxe.int.aibrokerapiurl - ignore_errors: true - - - name: "Remove existing AI Service tenant ID property (if any)" - kubernetes.core.k8s_json_patch: - api_version: v1 - kind: Secret - name: "{{ manage_encryption_secret_name }}" - namespace: "{{ manage_namespace }}" - patch: - - op: remove - path: /data/mxe.int.aibrokertenantid - ignore_errors: true - - - name: "Add AI Service properties to secret" - kubernetes.core.k8s_json_patch: - api_version: v1 - kind: Secret - name: "{{ manage_encryption_secret_name }}" - namespace: "{{ manage_namespace }}" - patch: - - op: add - path: /data/mxe.int.aibrokerapikey - value: "{{ encoded_apikey }}" - - op: add - path: /data/mxe.int.aibrokerapiurl - value: "{{ encoded_url }}" - - op: add - path: /data/mxe.int.aibrokertenantid - value: "{{ encoded_tenantid }}" - - -# Step 5: Verify the secret was updated -# ----------------------------------------------------------------------------- -- name: "Step 5: Verify AI Service properties in secret" - block: - - name: "Get updated secret" - kubernetes.core.k8s_info: - api_version: v1 - kind: Secret - name: "{{ manage_encryption_secret_name }}" - namespace: "{{ manage_namespace }}" - register: updated_secret_output - - - name: "Verify mxe.int.aibrokerapikey is present" - assert: - that: "'mxe.int.aibrokerapikey' in updated_secret_output.resources[0].data" - success_msg: "Verified: mxe.int.aibrokerapikey is present in secret" - fail_msg: "Failed: mxe.int.aibrokerapikey is not present in secret" - - - name: "Verify mxe.int.aibrokerapiurl is present" - assert: - that: "'mxe.int.aibrokerapiurl' in updated_secret_output.resources[0].data" - success_msg: "Verified: mxe.int.aibrokerapiurl is present in secret" - fail_msg: "Failed: mxe.int.aibrokerapiurl is not present in secret" - - - name: "Verify mxe.int.aibrokertenantid is present" - assert: - that: "'mxe.int.aibrokertenantid' in updated_secret_output.resources[0].data" - success_msg: "Verified: mxe.int.aibrokertenantid is present in secret" - fail_msg: "Failed: mxe.int.aibrokertenantid is not present in secret" - -# Step 6: Import AI Service TLS certificate into Manage truststore -# ----------------------------------------------------------------------------- -- name: "Step 6: Import AI Service TLS certificate into Manage" - block: - - name: "Get AI Service TLS certificate from secret" - kubernetes.core.k8s_info: - api_version: v1 - kind: Secret - name: "{{ aiservice_instance_id }}-public-aibroker-tls" - namespace: "{{ aiservice_namespace }}" - register: aiservice_tls_secret_output - - - name: "Fail if AI Service TLS secret not found" - fail: - msg: "Could not find AI Service TLS secret: {{ aiservice_instance_id }}-public-aibroker-tls in namespace {{ aiservice_namespace }}" - when: aiservice_tls_secret_output.resources | length == 0 - - - name: "Extract TLS certificate from secret" - set_fact: - aiservice_tls_cert: "{{ aiservice_tls_secret_output.resources[0].data['ca.crt'] | b64decode }}" - - - name: "Verify TLS certificate was retrieved" - fail: - msg: "Could not retrieve AI Service TLS certificate from secret" - when: aiservice_tls_cert is not defined or aiservice_tls_cert == "" - - - name: "Build certificate entry for ManageWorkspace" - set_fact: - aiservice_cert_entry: - - alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: "{{ aiservice_tls_cert }}" - - - name: "Import AI Service TLS certificate into ManageWorkspace" - kubernetes.core.k8s_json_patch: - api_version: apps.mas.ibm.com/v1 - kind: ManageWorkspace - name: "{{ mas_instance_id }}-{{ mas_workspace_id }}" - namespace: "mas-{{ mas_instance_id }}-manage" - patch: - - op: add - path: /spec/settings/deployment/importedCerts - value: "{{ aiservice_cert_entry }}" - -# Step 7: Verify AI Service health -# ----------------------------------------------------------------------------- -- name: "Step 7: Verify AI Service is running and healthy" - block: - - name: "Get aibroker route host" - kubernetes.core.k8s_info: - api_version: route.openshift.io/v1 - kind: Route - name: aibroker - namespace: "{{ aiservice_namespace }}" - register: aibroker_route_output - - - name: "Fail if aibroker route not found" - fail: - msg: "Could not find aibroker route in namespace {{ aiservice_namespace }}" - when: aibroker_route_output.resources | length == 0 - - - name: "Extract aibroker host" - set_fact: - aibroker_host: "{{ aibroker_route_output.resources[0].spec.host }}" - - - name: "Set AI Service health URL" - set_fact: - aiservice_health_url: "https://{{ aibroker_host }}/ibm/aibroker/service/rest/api/v1/health" - - - name: "Check AI Service health endpoint" - uri: - url: "{{ aiservice_health_url }}" - method: GET - validate_certs: false - return_content: true - status_code: [200, 503] - register: aiservice_health_response - retries: 5 - delay: 10 - until: - - aiservice_health_response.status == 200 - - aiservice_health_response.json is defined - failed_when: false - - - name: "Fail if health endpoint never returned 200" - fail: - msg: "AI Service health endpoint failed to return HTTP 200 after 5 attempts. Last status: {{ aiservice_health_response.status }}" - when: aiservice_health_response.status != 200 - - - name: "Parse AI Service health response" - set_fact: - aiservice_kmodel_status: "{{ aiservice_health_response.json.kmodel | default('unknown') }}" - aiservice_healthy_status: "{{ aiservice_health_response.json.healthy | default(false) }}" - - - name: "Display AI Service health status" - debug: - msg: - - "AI Service Health Check:" - - " URL: {{ aiservice_health_url }}" - - " kmodel: {{ aiservice_kmodel_status }}" - - " healthy: {{ aiservice_healthy_status }}" - - - name: "Verify AI Service is fully healthy" - assert: - that: - - aiservice_kmodel_status == 'running' - - aiservice_healthy_status == true - success_msg: "AI Service is running and healthy" - fail_msg: | - AI Service is not fully healthy: - - kmodel: {{ aiservice_kmodel_status }} (expected: running) - - healthy: {{ aiservice_healthy_status }} (expected: true) - -- name: "AI Service configuration completed successfully" - debug: - msg: - - "AI Service properties configured in Manage encryption secret successfully" - - "AI Service TLS certificate imported into Manage truststore" - - "AI Service health verified - service is running and healthy" - - "Note: Manage will automatically restart to apply these changes" diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml b/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml deleted file mode 100644 index da8a8e34aa..0000000000 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/tasks/main.yml +++ /dev/null @@ -1,75 +0,0 @@ ---- -# Assertions: preliminary validations -# ----------------------------------------------------------------------------- - -# Assertion: mas_instance_id is required -- name: "Fail if mas_instance_id is not provided" - assert: - that: mas_instance_id is defined and mas_instance_id != "" - fail_msg: "mas_instance_id property is required" - -# Assertion: mas_workspace_id is required -- name: "Fail if mas_workspace_id is not provided" - assert: - that: mas_workspace_id is defined and mas_workspace_id != "" - fail_msg: "mas_workspace_id property is required" - -# Assertion: aiservice_instance_id is required -- name: "Fail if aiservice_instance_id is not provided" - assert: - that: aiservice_instance_id is defined and aiservice_instance_id != "" - fail_msg: "aiservice_instance_id property is required" - -# Assertion: mas_app_id must be 'manage' -- name: "Fail if mas_app_id is not 'manage'" - assert: - that: - - mas_app_id is defined and mas_app_id != "" - - mas_app_id == 'manage' - fail_msg: "mas_app_id property is required and must be set to 'manage'" - -# Check CM: if AI Service is already configured via internal config map -# ----------------------------------------------------------------------------- -- name: "Check CM: if AI Service is already configured via internal config map" - kubernetes.core.k8s_info: - api_version: v1 - kind: ConfigMap - name: "{{ mas_instance_id }}-{{ mas_workspace_id }}-manage-aiservice-configmap" - namespace: "{{ manage_namespace }}" - register: manage_aiservice_cm_output - -- set_fact: - mas_manage_aiservice_configured: "{{ manage_aiservice_cm_output.resources | length > 0 }}" - mas_manage_aiservice_version: "{{ manage_aiservice_cm_output.resources[0].data.aiservice_instance_id | default('', true) if manage_aiservice_cm_output.resources | length > 0 else '' }}" - -- name: Debug - debug: - msg: - - "mas_instance_id ................................... {{ mas_instance_id }}" - - "mas_workspace_id .................................. {{ mas_workspace_id }}" - - "mas_app_id ........................................ {{ mas_app_id }}" - - "" - - "aiservice_instance_id ............................. {{ aiservice_instance_id }}" - - "aiservice_namespace ............................... {{ aiservice_namespace }}" - - "" - - "manage_namespace .................................. {{ manage_namespace }}" - - "manage_encryption_secret_name ..................... {{ manage_encryption_secret_name }}" - - "" - - "mas_manage_aiservice_configured ................... {{ mas_manage_aiservice_configured }}" - - "mas_manage_aiservice_version (existing) ........... {{ mas_manage_aiservice_version }}" - - "" - - "{{ (mas_manage_aiservice_version == aiservice_instance_id) | ternary('AI Service is already configured for this instance, skipping configuration','AI Service is not configured or instance has changed, proceeding with configuration...') }}" - -# Configure AI Service properties -# ----------------------------------------------------------------------------- -- name: "Configure AI Service properties in Manage" - include_tasks: "configure.yml" - when: mas_manage_aiservice_version != aiservice_instance_id # only configure when AI Service is not setup yet or instance changed - -# Set CM: config map to track AI Service configuration (keep idempotency of ansible role) -# ----------------------------------------------------------------------------- -- name: "Set CM: config map to track AI Service configuration" - kubernetes.core.k8s: - apply: yes - template: "templates/configmap.yml.j2" - when: mas_manage_aiservice_version != aiservice_instance_id # only configure when AI Service is not setup yet or instance changed diff --git a/ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 b/ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 deleted file mode 100644 index 45072606ec..0000000000 --- a/ibm/mas_devops/roles/suite_manage_aiservice_config/templates/configmap.yml.j2 +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: "{{ mas_instance_id }}-{{ mas_workspace_id }}-manage-aiservice-configmap" - namespace: "{{ manage_namespace }}" - labels: - mas.ibm.com/instanceId: "{{ mas_instance_id }}" - mas.ibm.com/workspaceId: "{{ mas_workspace_id }}" - mas.ibm.com/applicationId: "{{ mas_app_id }}" -data: - aiservice_instance_id: "{{ aiservice_instance_id }}" - aiservice_namespace: "{{ aiservice_namespace }}" - configured_at: "{{ ansible_date_time.iso8601 }}" diff --git a/mkdocs.yml b/mkdocs.yml index 8ec93d9b60..a7299f615c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -85,7 +85,6 @@ nav: - "suite_db2_setup_for_manage": roles/suite_db2_setup_for_manage.md - "suite_dns": roles/suite_dns.md - "suite_install": roles/suite_install.md - - "suite_manage_aiservice_config": roles/suite_manage_aiservice_config.md - "suite_manage_attachments_config": roles/suite_manage_attachments_config.md - "suite_manage_birt_report_config": roles/suite_manage_birt_report_config.md - "suite_manage_bim_config": roles/suite_manage_bim_config.md From a2478e939be09ffff5413cc17a0340406f76f9bc Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Mon, 15 Dec 2025 16:51:46 +0530 Subject: [PATCH 10/27] [patch] re-build --- .../roles/suite_app_config/tasks/manage/pre-config/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml index e322acbf69..8692e0a711 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml @@ -33,7 +33,7 @@ - mas_app_settings_customization_archive_url | length > 0 include_tasks: "tasks/manage/pre-config/setup-custom-archive.yml" -# Manage pre-configuration: AI Service integration setup +# Manage pre-configuration: AI Service configuration setup - name: "Run Manage specific pre-configuration: Set up AI Service integration" when: - aiservice_instance_id is defined From 0a633865a60c348aa7b62701de75b6815fafae80 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Mon, 15 Dec 2025 20:07:12 +0530 Subject: [PATCH 11/27] [patch] keep aiservice_tenant_id as mandatory --- .../tasks/manage/pre-config/main.yml | 3 ++ .../pre-config/setup-aiservice-config.yml | 41 +++++++------------ .../manage/encryption-secrets.yml.j2 | 4 +- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml index 8692e0a711..3bbbd048fe 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml @@ -38,6 +38,9 @@ when: - aiservice_instance_id is defined - aiservice_instance_id != "" + - aiservice_tenant_id is defined + - aiservice_tenant_id != "" + include_tasks: "tasks/manage/pre-config/setup-aiservice-config.yml" # Manage pre-configuration: Database encryption and AI Service secrets setup diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 7c69dfd6c3..96ea8d997c 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -8,31 +8,17 @@ - set_fact: aiservice_namespace: "aiservice-{{ aiservice_instance_id }}" -# Step 1: Retrieve AI Service tenant ID from AIServiceTenant custom resource +# Step 1: Construct fully qualified tenant name # ------------------------------------------------------------------------ -- name: "Step 1: Retrieve AI Service tenant ID from AIServiceTenant CR if not explicitly provided" - when: aiservice_tenant_id is not defined or aiservice_tenant_id == "" - block: - - name: "List all AIServiceTenant CRs in AI Service namespace" - kubernetes.core.k8s_info: - api_version: aiservice.ibm.com/v1 - kind: AIServiceTenant - namespace: "{{ aiservice_namespace }}" - register: aiservice_tenants_list - - - name: "Fail if no AIServiceTenant CRs found" - fail: - msg: "No AIServiceTenant CRs found in namespace '{{ aiservice_namespace }}'. Please ensure AI Service is properly installed." - when: - - aiservice_tenants_list.resources is not defined or aiservice_tenants_list.resources | length == 0 - - - name: "Extract first tenant name" - set_fact: - aiservice_tenant_id: "{{ aiservice_tenants_list.resources[0].metadata.name }}" +- name: "Construct fully qualified AI Service tenant name" + set_fact: + aiservice_tenant_fqn: "aiservice-{{ aiservice_instance_id }}-{{ aiservice_tenant_id }}" - - name: "Debug: AI Servicetenant ID" - debug: - msg: "AI Service tenant ID: {{ aiservice_tenant_id }}" +- name: "Debug: AI Service tenant information" + debug: + msg: + - "AI Service tenant ID ............................... {{ aiservice_tenant_id }}" + - "AI Service tenant FQN .............................. {{ aiservice_tenant_fqn }}" # Step 2: Retrieve AI Service API key (tenant-specific) # ------------------------------------------------------------------------ @@ -40,13 +26,13 @@ kubernetes.core.k8s_info: api_version: v1 kind: Secret - name: "{{ aiservice_tenant_id }}----apikey-secret" + name: "{{ aiservice_tenant_fqn }}----apikey-secret" namespace: "{{ aiservice_namespace }}" register: aiservice_apikey_secret - name: "Fail if AI Service tenant API key secret not found" fail: - msg: "AI Service tenant API key secret '{{ aiservice_tenant_id }}----apikey-secret' not found in namespace '{{ aiservice_namespace }}'" + msg: "AI Service tenant API key secret '{{ aiservice_tenant_fqn }}----apikey-secret' not found in namespace '{{ aiservice_namespace }}'" when: - aiservice_apikey_secret.resources is not defined or aiservice_apikey_secret.resources | length == 0 @@ -165,8 +151,9 @@ - name: "Debug AI Service configuration" debug: msg: - - "AI Service instance ID ............................ {{ aiservice_instance_id }}" - - "AI Service tenant ID .............................. {{ aiservice_tenant_id }}" + - "AI Service instance ID ............................. {{ aiservice_instance_id }}" + - "AI Service tenant ID ............................... {{ aiservice_tenant_id }}" + - "AI Service tenant FQN .............................. {{ aiservice_tenant_fqn }}" - "AI Service namespace ............................... {{ aiservice_namespace }}" - "AI Service URL ..................................... {{ aiservice_url }}" - "AI Service certificate alias ....................... {{ aiservice_cert_alias }}" diff --git a/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 b/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 index 2fb75d1f56..b1c6ac377e 100644 --- a/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 +++ b/ibm/mas_devops/roles/suite_app_config/templates/manage/encryption-secrets.yml.j2 @@ -28,6 +28,6 @@ stringData: {% if aiservice_url is defined and aiservice_url !='' %} mxe.int.aibrokerapiurl: {{ aiservice_url }} {% endif %} -{% if aiservice_tenant_id is defined and aiservice_tenant_id !='' %} - mxe.int.aibrokertenantid: {{ aiservice_tenant_id }} +{% if aiservice_tenant_fqn is defined and aiservice_tenant_fqn !='' %} + mxe.int.aibrokertenantid: {{ aiservice_tenant_fqn }} {% endif %} From cfdbbb3678e7879d8b3deea5b699ce6c34b090e1 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Mon, 15 Dec 2025 20:23:18 +0530 Subject: [PATCH 12/27] fix aiservice cert issue --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 96ea8d997c..3d43ce8531 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -92,7 +92,8 @@ aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" aiservice_cert_import: alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: "{{ aiservice_tls_cert }}" + crt: | + {{ aiservice_tls_cert }} # Step 6: Verify AI Service is running and healthy # ------------------------------------------------------------------------ From 38041ee4d3136d0825804009227b6c93123df3f0 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Mon, 15 Dec 2025 21:05:33 +0530 Subject: [PATCH 13/27] set default aiservice_tenant_id for test --- .../suite_app_config/tasks/manage/pre-config/main.yml | 3 --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 9 ++++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml index 3bbbd048fe..8692e0a711 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/main.yml @@ -38,9 +38,6 @@ when: - aiservice_instance_id is defined - aiservice_instance_id != "" - - aiservice_tenant_id is defined - - aiservice_tenant_id != "" - include_tasks: "tasks/manage/pre-config/setup-aiservice-config.yml" # Manage pre-configuration: Database encryption and AI Service secrets setup diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 3d43ce8531..26bbde20fd 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -8,7 +8,14 @@ - set_fact: aiservice_namespace: "aiservice-{{ aiservice_instance_id }}" -# Step 1: Construct fully qualified tenant name +# Step 1: Set default tenant ID if not provided +# ------------------------------------------------------------------------ +- name: "Set default AI Service tenant ID if not provided" + set_fact: + aiservice_tenant_id: "user" + when: aiservice_tenant_id is not defined or aiservice_tenant_id == "" + +# Step 2: Construct fully qualified tenant name # ------------------------------------------------------------------------ - name: "Construct fully qualified AI Service tenant name" set_fact: From d4dab1826f88446b37d1618a16289dca17336c21 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 17:45:06 +0530 Subject: [PATCH 14/27] [patch] fix already exists properties and cert issue --- .../pre-config/setup-aiservice-config.yml | 3 +- .../pre-config/setup-encryption-secret.yml | 50 +++++++++++++++++++ .../vars/defaultspecs/manage.yml | 2 +- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 26bbde20fd..4b96f211f1 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -99,8 +99,7 @@ aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" aiservice_cert_import: alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: | - {{ aiservice_tls_cert }} + crt: "{{ aiservice_tls_cert }}" # Step 6: Verify AI Service is running and healthy # ------------------------------------------------------------------------ diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-encryption-secret.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-encryption-secret.yml index cd5ab0522a..5142ae40ec 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-encryption-secret.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-encryption-secret.yml @@ -88,6 +88,56 @@ - is_encryption_secret_existing - mas_app_settings_override_encryption_secrets_flag +# Update existing secret with AI Service properties if needed +# This handles the case where the secret exists but doesn't have AI Service properties yet +- block: + - name: "Lookup existing {{ mas_app_settings_encryption_secret_name }} secret for AI Service update" + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ mas_app_settings_encryption_secret_name }}" + namespace: "mas-{{ mas_instance_id }}-{{ mas_app_id }}" + register: existing_secret_for_update + + - name: "Check if AI Service properties are missing in existing secret" + set_fact: + needs_aiservice_update: "{{ (existing_secret_for_update.resources[0].data['mxe.int.aibrokerapikey'] is not defined or existing_secret_for_update.resources[0].data['mxe.int.aibrokerapiurl'] is not defined or existing_secret_for_update.resources[0].data['mxe.int.aibrokertenantid'] is not defined) and (aiservice_api_key is defined and aiservice_api_key != '' and aiservice_url is defined and aiservice_url != '' and aiservice_tenant_fqn is defined and aiservice_tenant_fqn != '') }}" + + - name: "Debug: AI Service update needed" + debug: + msg: + - "AI Service properties missing in secret? ................ {{ needs_aiservice_update }}" + - "Will update existing secret with AI Service properties" + when: needs_aiservice_update + + - name: "Update existing secret with AI Service properties" + no_log: true + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Secret + metadata: + name: "{{ mas_app_settings_encryption_secret_name }}" + namespace: "mas-{{ mas_instance_id }}-{{ mas_app_id }}" + stringData: + # Preserve existing DB encryption keys + MXE_SECURITY_CRYPTO_KEY: "{{ existing_secret_for_update.resources[0].data.MXE_SECURITY_CRYPTO_KEY | b64decode }}" + MXE_SECURITY_CRYPTOX_KEY: "{{ existing_secret_for_update.resources[0].data.MXE_SECURITY_CRYPTOX_KEY | b64decode }}" + # Preserve old keys if they exist + MXE_SECURITY_OLD_CRYPTO_KEY: "{{ existing_secret_for_update.resources[0].data.MXE_SECURITY_OLD_CRYPTO_KEY | b64decode if existing_secret_for_update.resources[0].data.MXE_SECURITY_OLD_CRYPTO_KEY is defined else '' }}" + MXE_SECURITY_OLD_CRYPTOX_KEY: "{{ existing_secret_for_update.resources[0].data.MXE_SECURITY_OLD_CRYPTOX_KEY | b64decode if existing_secret_for_update.resources[0].data.MXE_SECURITY_OLD_CRYPTOX_KEY is defined else '' }}" + # Add AI Service properties + mxe.int.aibrokerapikey: "{{ aiservice_api_key }}" + mxe.int.aibrokerapiurl: "{{ aiservice_url }}" + mxe.int.aibrokertenantid: "{{ aiservice_tenant_fqn }}" + when: needs_aiservice_update + + when: + - is_encryption_secret_existing + - not mas_app_settings_override_encryption_secrets_flag + - aiservice_api_key is defined and aiservice_api_key != '' + # then, finally create the encryption secret if does not exist # or create the new replacing secret with the new credentials if mas_app_settings_override_encryption_secrets_flag is True - name: "Create secret containing {{ mas_app_id }} database encryption keys" diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index b92155e8ef..39a1da1137 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,7 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" - importedCerts: "{{ [aiservice_cert_import] if (aiservice_cert_import is defined) else [] }}" + importedCerts: "{{ [aiservice_cert_import | to_json | from_json] if (aiservice_cert_import is defined) else [] }}" languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}" From 2c59e8ff5cb3d4e3a643f4ae27c658059c1ecfaf Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 18:01:06 +0530 Subject: [PATCH 15/27] fix crt issue --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 3 ++- .../roles/suite_app_config/vars/defaultspecs/manage.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 4b96f211f1..26bbde20fd 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -99,7 +99,8 @@ aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" aiservice_cert_import: alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: "{{ aiservice_tls_cert }}" + crt: | + {{ aiservice_tls_cert }} # Step 6: Verify AI Service is running and healthy # ------------------------------------------------------------------------ diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index 39a1da1137..c8551b4de2 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,7 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" - importedCerts: "{{ [aiservice_cert_import | to_json | from_json] if (aiservice_cert_import is defined) else [] }}" + importedCerts: "{{ [aiservice_cert_import | to_yaml | from_yaml] if (aiservice_cert_import is defined) else [] }}" languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}" From 5d3e87d85c53046776619171ee0b7a999ed732df Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 18:22:17 +0530 Subject: [PATCH 16/27] Update setup-aiservice-config.yml --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 26bbde20fd..e39e0d5488 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -90,7 +90,7 @@ - name: "Extract AI Service TLS certificate" set_fact: - aiservice_tls_cert: "{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode }}" + aiservice_tls_cert: "{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode | replace('\\\\n', '\n') | replace('\\n', '\n') }}" # Step 5: Set certificate import configuration # ------------------------------------------------------------------------ From 4049c8b11932b34063395b35aa9a2f74e947674c Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 18:25:08 +0530 Subject: [PATCH 17/27] debug --- .../manage/pre-config/setup-aiservice-config.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index e39e0d5488..accb168a48 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -92,6 +92,13 @@ set_fact: aiservice_tls_cert: "{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode | replace('\\\\n', '\n') | replace('\\n', '\n') }}" +- name: "Debug: Verify certificate format" + debug: + msg: + - "Certificate first 100 chars: {{ aiservice_tls_cert[:100] }}" + - "Certificate contains actual newlines: {{ '\n' in aiservice_tls_cert }}" + - "Certificate line count: {{ aiservice_tls_cert.split('\n') | length }}" + # Step 5: Set certificate import configuration # ------------------------------------------------------------------------ - name: "Step 5: Set AI Service certificate import configuration" @@ -102,6 +109,13 @@ crt: | {{ aiservice_tls_cert }} +- name: "Debug: Verify certificate import structure" + debug: + msg: + - "Certificate alias: {{ aiservice_cert_import.alias }}" + - "Certificate crt field type: {{ aiservice_cert_import.crt | type_debug }}" + - "Certificate crt first 100 chars: {{ aiservice_cert_import.crt[:100] }}" + # Step 6: Verify AI Service is running and healthy # ------------------------------------------------------------------------ - name: "Step 6: Verify AI Service is running and healthy" From 12a567ec2a91b4675b267bae4950aa7a4724930f Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 19:29:29 +0530 Subject: [PATCH 18/27] [patch] fix cert issue --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 6 +++--- .../roles/suite_app_config/vars/defaultspecs/manage.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index accb168a48..d114130797 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -105,9 +105,9 @@ set_fact: aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" aiservice_cert_import: - alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: | - {{ aiservice_tls_cert }} + - alias: "aiservice-{{ aiservice_instance_id }}-tls1" + crt: | + {{ aiservice_tls_cert }} - name: "Debug: Verify certificate import structure" debug: diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index c8551b4de2..d279814a52 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,7 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" - importedCerts: "{{ [aiservice_cert_import | to_yaml | from_yaml] if (aiservice_cert_import is defined) else [] }}" + importedCerts: "{{ aiservice_cert_import if (aiservice_cert_import is defined and aiservice_cert_import | length > 0) else omit }}" languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}" From 0cbdcf578c5ed61981878aee2151683a619ef783 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 20:30:57 +0530 Subject: [PATCH 19/27] Update setup-aiservice-config.yml --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index d114130797..c29210147c 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -106,15 +106,15 @@ aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" aiservice_cert_import: - alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: | - {{ aiservice_tls_cert }} + crt: "{{ aiservice_tls_cert }}" - name: "Debug: Verify certificate import structure" debug: msg: - - "Certificate alias: {{ aiservice_cert_import.alias }}" - - "Certificate crt field type: {{ aiservice_cert_import.crt | type_debug }}" - - "Certificate crt first 100 chars: {{ aiservice_cert_import.crt[:100] }}" + - "Certificate import is a list: {{ aiservice_cert_import | type_debug }}" + - "Certificate count: {{ aiservice_cert_import | length }}" + - "Certificate crt field type: {{ aiservice_cert_import[0].crt | type_debug }}" + - "Certificate crt first 100 chars: {{ aiservice_cert_import[0].crt[:100] }}" # Step 6: Verify AI Service is running and healthy # ------------------------------------------------------------------------ From 263e4746d160bf2f155585d53425e996a8d6b499 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 22:47:28 +0530 Subject: [PATCH 20/27] Update setup-aiservice-config.yml --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index c29210147c..256424fea6 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -90,7 +90,7 @@ - name: "Extract AI Service TLS certificate" set_fact: - aiservice_tls_cert: "{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode | replace('\\\\n', '\n') | replace('\\n', '\n') }}" + aiservice_tls_cert: "{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode }}" - name: "Debug: Verify certificate format" debug: @@ -106,7 +106,8 @@ aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" aiservice_cert_import: - alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: "{{ aiservice_tls_cert }}" + crt: | + {{ aiservice_tls_cert | indent(10) }} - name: "Debug: Verify certificate import structure" debug: From b531d2e34c9a9796bde7dbe77ca29946f385d00f Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Tue, 16 Dec 2025 23:22:40 +0530 Subject: [PATCH 21/27] [patch] --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 3 +-- .../roles/suite_app_config/vars/defaultspecs/manage.yml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 256424fea6..71dd336c62 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -106,8 +106,7 @@ aiservice_cert_alias: "aiservice-{{ aiservice_instance_id }}-tls1" aiservice_cert_import: - alias: "aiservice-{{ aiservice_instance_id }}-tls1" - crt: | - {{ aiservice_tls_cert | indent(10) }} + crt: "{{ aiservice_tls_cert }}" - name: "Debug: Verify certificate import structure" debug: diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index d279814a52..74f1261b88 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,7 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" - importedCerts: "{{ aiservice_cert_import if (aiservice_cert_import is defined and aiservice_cert_import | length > 0) else omit }}" + importedCerts: “{{ (aiservice_cert_import | to_json | from_json) if (aiservice_cert_import is defined and aiservice_cert_import | length > 0) else omit }}” languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}" From 4b1be84d839bb74a2d1c30837e1d6e1825e423a8 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 17 Dec 2025 00:36:54 +0530 Subject: [PATCH 22/27] [patch] use new file --- .../suite_app_config/templates/manage/aiservice-cert.yml.j2 | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 diff --git a/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 b/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 new file mode 100644 index 0000000000..c43504ef88 --- /dev/null +++ b/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 @@ -0,0 +1,5 @@ +{% for cert in aiservice_cert_import %} +- alias: "{{ cert.alias }}" + crt: | + {{ cert.crt | indent(4) }} +{% endfor %} From 815134505280468acaefbe9be5738624202655b4 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 17 Dec 2025 00:39:11 +0530 Subject: [PATCH 23/27] use diff file --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 5 +++++ .../roles/suite_app_config/vars/defaultspecs/manage.yml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 71dd336c62..8aeebc24ce 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -108,6 +108,10 @@ - alias: "aiservice-{{ aiservice_instance_id }}-tls1" crt: "{{ aiservice_tls_cert }}" +- name: "Render certificate import template to YAML" + set_fact: + aiservice_cert_import_yaml: "{{ lookup('template', 'manage/aiservice-cert.yml.j2') | from_yaml }}" + - name: "Debug: Verify certificate import structure" debug: msg: @@ -115,6 +119,7 @@ - "Certificate count: {{ aiservice_cert_import | length }}" - "Certificate crt field type: {{ aiservice_cert_import[0].crt | type_debug }}" - "Certificate crt first 100 chars: {{ aiservice_cert_import[0].crt[:100] }}" + - "Rendered YAML type: {{ aiservice_cert_import_yaml | type_debug }}" # Step 6: Verify AI Service is running and healthy # ------------------------------------------------------------------------ diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index 74f1261b88..ab5d53977d 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,7 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" - importedCerts: “{{ (aiservice_cert_import | to_json | from_json) if (aiservice_cert_import is defined and aiservice_cert_import | length > 0) else omit }}” + importedCerts: "{{ aiservice_cert_import_yaml if (aiservice_cert_import_yaml is defined and aiservice_cert_import_yaml | length > 0) else omit }}" languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}" From 294f0449609cc3bc55cdfa45012c566158567977 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 17 Dec 2025 11:47:38 +0530 Subject: [PATCH 24/27] Update workspace.yml.j2 --- .../roles/suite_app_config/templates/workspace.yml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 b/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 index 1413eb819a..5205309f4b 100644 --- a/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 +++ b/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 @@ -13,4 +13,4 @@ metadata: {{ key }}: "{{ value }}" {% endfor %} {% endif %} -spec: {{ mas_appws_spec }} +spec: {{ mas_appws_spec | to_nice_yaml(indent=2) | indent(2) }} From 80270b962ec27d9da5b4ba7a60efcb323f07b1a2 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 17 Dec 2025 14:16:16 +0530 Subject: [PATCH 25/27] test --- .../tasks/manage/pre-config/setup-aiservice-config.yml | 2 +- .../suite_app_config/templates/manage/aiservice-cert.yml.j2 | 2 +- .../roles/suite_app_config/templates/workspace.yml.j2 | 2 +- .../roles/suite_app_config/vars/defaultspecs/manage.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml index 8aeebc24ce..ba00609af1 100644 --- a/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml +++ b/ibm/mas_devops/roles/suite_app_config/tasks/manage/pre-config/setup-aiservice-config.yml @@ -90,7 +90,7 @@ - name: "Extract AI Service TLS certificate" set_fact: - aiservice_tls_cert: "{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode }}" + aiservice_tls_cert: “{{ aiservice_tls_secret.resources[0].data['ca.crt'] | b64decode | replace('\r\n', '\n') | replace('\r', '\n') }}” - name: "Debug: Verify certificate format" debug: diff --git a/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 b/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 index c43504ef88..0ab37e45dc 100644 --- a/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 +++ b/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 @@ -1,5 +1,5 @@ {% for cert in aiservice_cert_import %} - alias: "{{ cert.alias }}" crt: | - {{ cert.crt | indent(4) }} + {{ cert.crt | indent(4, first=True) }} {% endfor %} diff --git a/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 b/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 index 5205309f4b..1413eb819a 100644 --- a/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 +++ b/ibm/mas_devops/roles/suite_app_config/templates/workspace.yml.j2 @@ -13,4 +13,4 @@ metadata: {{ key }}: "{{ value }}" {% endfor %} {% endif %} -spec: {{ mas_appws_spec | to_nice_yaml(indent=2) | indent(2) }} +spec: {{ mas_appws_spec }} diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index ab5d53977d..4531759bdb 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,7 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" - importedCerts: "{{ aiservice_cert_import_yaml if (aiservice_cert_import_yaml is defined and aiservice_cert_import_yaml | length > 0) else omit }}" + importedCerts: “{{ lookup(‘template’, ‘manage/aiservice-cert.yml.j2’) | from_yaml if (aiservice_cert_import is defined and aiservice_cert_import | length > 0) else omit }}” languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}" From 4b3ae49f8e2d535ed49231f05f5914d77927d997 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 17 Dec 2025 15:12:34 +0530 Subject: [PATCH 26/27] Update aiservice-cert.yml.j2 --- .../suite_app_config/templates/manage/aiservice-cert.yml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 b/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 index 0ab37e45dc..c43504ef88 100644 --- a/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 +++ b/ibm/mas_devops/roles/suite_app_config/templates/manage/aiservice-cert.yml.j2 @@ -1,5 +1,5 @@ {% for cert in aiservice_cert_import %} - alias: "{{ cert.alias }}" crt: | - {{ cert.crt | indent(4, first=True) }} + {{ cert.crt | indent(4) }} {% endfor %} From 57ddd925e798eed511b1837e158131270011ea82 Mon Sep 17 00:00:00 2001 From: Divyesh Khokhar Date: Wed, 17 Dec 2025 16:09:33 +0530 Subject: [PATCH 27/27] Update manage.yml --- .../roles/suite_app_config/vars/defaultspecs/manage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml index 4531759bdb..c120e78dac 100644 --- a/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml +++ b/ibm/mas_devops/roles/suite_app_config/vars/defaultspecs/manage.yml @@ -10,7 +10,7 @@ mas_appws_spec: serverBundles: "{{ is_full_manage | ternary(mas_app_settings_server_bundles[mas_app_settings_server_bundles_size]['serverBundles'], []) }}" defaultJMS: "{{ mas_app_settings_default_jms }}" serverTimezone: "{{ mas_app_settings_server_timezone }}" - importedCerts: “{{ lookup(‘template’, ‘manage/aiservice-cert.yml.j2’) | from_yaml if (aiservice_cert_import is defined and aiservice_cert_import | length > 0) else omit }}” + importedCerts: "{{ (lookup('template', 'manage/aiservice-cert.yml.j2') | from_yaml) if (aiservice_cert_import is defined and aiservice_cert_import | length > 0) else omit }}" languages: baseLang: "{{ mas_app_settings_base_lang | default('EN' , true) }}" secondaryLangs: "{{ mas_app_settings_secondary_langs.split(',') if (mas_app_settings_secondary_langs is defined and mas_app_settings_secondary_langs is not none and mas_app_settings_secondary_langs | length > 0) else [] }}"