Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0d9b57e
feat(mcpi-cli-install): add mcpi-install CLI command and Tekton pipeline
tahamadou-bah Aug 27, 2026
892a577
style(mcpi-cli-install): replace quoted descriptions with unquoted fo…
tahamadou-bah Aug 27, 2026
e59d113
style(mcpi-cli-install): quote mcpi CLI image reference
tahamadou-bah Sep 3, 2026
33091ab
Merge branch 'master' of https://github.com/ibm-mas/cli into mcpi-cli…
tahamadou-bah Sep 3, 2026
f2d89ce
feat(mcpi-cli-install): add mcpi-install command routing in CLI
tahamadou-bah Sep 3, 2026
7a682a4
docs(mcpi-cli-install): add mcpi-install entry to CLI help text
tahamadou-bah Sep 8, 2026
0cc8971
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Sep 15, 2026
ed77f88
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Sep 22, 2026
44bc2c8
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Sep 24, 2026
c8101a8
refactor(mcpi-cli-install): remove redundant params from mcpi-install…
tahamadou-bah Sep 24, 2026
0d5d7e7
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Sep 28, 2026
38b7419
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Sep 29, 2026
49da514
feat(mcpi-cli-install): add SLS, DRO, cert manager and ICR params to …
tahamadou-bah Oct 1, 2026
f3f0cff
Merge branch 'master' of https://github.com/ibm-mas/cli into mcpi-cli…
tahamadou-bah Oct 1, 2026
607af42
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Oct 6, 2026
9e99a22
fix(mcpi-cli-install): skip license file requirement when reusing SLS
tahamadou-bah Oct 7, 2026
01edc07
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Oct 7, 2026
6604ef6
fix(mcpi-cli-install): update jsonpath_ng import to use ext.parser
tahamadou-bah Oct 7, 2026
6bba968
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Oct 8, 2026
2fe6849
refactor(mcpi-cli-install): remove routing mode and service mesh para…
tahamadou-bah Oct 9, 2026
2cce89e
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Oct 9, 2026
131d00f
Merge branch 'master' into mcpi-cli-install
tahamadou-bah Oct 10, 2026
366c661
refactor(mcpi-cli-install): replace standalone mcpi-install command w…
tahamadou-bah Oct 11, 2026
d7ba653
test(mcpi-cli-install): add mcpi prompt response to interactive insta…
tahamadou-bah Oct 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
911 changes: 911 additions & 0 deletions .bob/plans/2025-01-31-mcpi-install.md

Large diffs are not rendered by default.

298 changes: 298 additions & 0 deletions .bob/plans/2025-06-11-mcpi-install-cleanup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
# MCPI Install Cleanup Plan

## Objective

Remove the over-engineered standalone `mcpi-install` command and pipeline across three repos, and replace with the minimal correct approach: a `--mcpi-channel` flag on the existing `mas-cli install` command that includes the `McpiCfg` CR via `additional-configs`, applied by the already-present `suite-config` Tekton task.

---

## Design Decisions

### Why the standalone approach was wrong

The over-built implementation treated MCPI like a standalone product (AI Service pattern) with its own:
- CLI command (`mas-cli mcpi-install`)
- Tekton pipeline (`mcpi-install.yml.j2`)
- Custom Tekton task (`mas-devops-mcpi`) running `gencfg_mcpicfg` + `suite_config`
- Ansible role (`gencfg_mcpicfg`) generating a `McpiCfg` CR
- python-devops namespace provisioning (`prepareMcpiPipelinesNamespace`, separate RBAC/PVC templates)

### The McpiCfg CR is trivially simple

`ibm/mas_devops/roles/gencfg_mcpicfg/templates/mcpicfg.yml.j2`:

```yaml
apiVersion: config.mas.ibm.com/v1
kind: McpiCfg
metadata:
name: "{{ mas_instance_id }}-mcpi-system"
namespace: "mas-{{ mas_instance_id }}-core"
labels:
mas.ibm.com/configScope: system
mas.ibm.com/instanceId: "{{ mas_instance_id }}"
spec:
displayName: "Maximo Cluster Performance Insights"
config:
enabled: true
```

There is no subscription channel, no database, no S3. The `mcpi_channel` param was never used in the CR template or anywhere in the `gencfg_mcpicfg` role — it was vestigial.

### How suite_config handles additional-configs

`run-role.sh` (line 3-5) copies `additional-configs/*` → `configs/` **before every role invocation**. The existing `suite-config` Tekton task calls `run-role.sh suite_config`. Therefore:

- If a `McpiCfg` YAML is placed in the `additional-configs` workspace, `suite_config` will automatically apply it
- The `McpiCfg` CR uses `{{ mas_instance_id }}` in name/namespace which `suite_config` resolves via `kubernetes.core.k8s template:`

### Decision: No new Tekton task needed, no `mcpi_channel` Tekton param needed

The existing `suite-config` step in `mas-install.yml.j2` is sufficient to apply the McpiCfg, as long as the CR YAML is present in `additional-configs`. No separate Tekton step, no new params file, no `mcpi_channel` pipeline parameter.

The `--mcpi-channel` CLI flag in `mas-cli install` serves as the user-facing gate. When set, the CLI:
1. Sets `self.installMcpi = True`
2. Sets `mcpi_channel` in params (for display in summary/argBuilder — the channel value itself isn't used functionally)
3. The McpiCfg YAML is bundled into the generated `additional-configs` secret when the `python-devops` `launchInstallPipeline` builds the PipelineRun

**Important**: Because `mcpi_channel` is not used in the CR, passing it as a Tekton pipeline param serves no purpose. The `--mcpi-channel` flag is needed only to:
- Signal that MCPI should be installed (gate)
- Display in the install summary
- Be reproducible via `buildCommand()`

---

## Critical Rules

- Track progress only by updating checkboxes in this plan file — do NOT use chat todo lists
- Delete files entirely rather than commenting them out
- Each phase must be independently validatable before proceeding to the next
- Do NOT add error handling or abstractions beyond the minimal patterns already used by other apps (e.g., `facilities_channel`)
- Preserve all unrelated content in files being partially edited
- When removing lines from `__main__.py`, `mascli/mas`, `.bashrc`, `pytest.ini` — verify surrounding context before editing

---

## Execution Plan

### Phase 1 — Delete over-built files

**Objective**: Remove all files that belong exclusively to the standalone mcpi-install implementation.

[ ] **1.1** Delete `python/src/mas/cli/mcpi/` (entire directory — 7 files)

[ ] **1.2** Delete `python/tests/integration/mcpi_install/` (entire directory — 3 files)

[ ] **1.3** Delete `tekton/src/pipelines/mcpi-install.yml.j2`

[ ] **1.4** Delete `tekton/src/tasks/mcpi/mcpi.yml.j2` and the `mcpi/` directory

[ ] **1.5** Delete `tekton/src/pipelines/taskdefs/mcpi/mcpi.yml.j2` and the `mcpi/` directory

[ ] **1.6** Delete `tekton/src/params/install-mcpi.yml.j2`

[ ] **1.7** Delete `ibm/mas_devops/roles/gencfg_mcpicfg/` (entire directory — 4 files across 4 subdirectories) in `ansible-devops` repo

[ ] **1.8** Delete `src/mas/devops/templates/mcpi-pipelines-pvc.yml.j2` in `python-devops` repo

[ ] **1.9** Delete `src/mas/devops/templates/mcpi-pipelines-rbac.yml.j2` in `python-devops` repo

[ ] **1.10** Delete `src/mas/devops/templates/pipelinerun-mcpi-install.yml.j2` in `python-devops` repo

[ ] **1.11** Delete `test/src/test_tekton_mcpi.py` in `python-devops` repo

**Validation**: Confirm none of the deleted paths exist. No build or test run needed yet.

---

### Phase 2 — Undo file modifications in `cli` repo

**Objective**: Revert all partial changes to shared files that were modified to support the standalone approach.

**Relevant files and what to undo:**

#### `tekton/src/params/install.yml.j2`
Remove the MCPI Configuration section (lines ~862-864):
```
# MCPI Configuration
{{ lookup('template', params_src_dir ~ '/install-mcpi.yml.j2') }}
```

#### `tekton/src/pipelines/mas-install.yml.j2`
- Remove section 15 "Install and configure MCPI" block (~lines 464-468):
```
# 15. Install and configure MCPI (Maximo Cluster Performance Insights)
# -------------------------------------------------------------------------
{{ lookup('template', pipeline_src_dir ~ '/taskdefs/mcpi/mcpi.yml.j2') | indent(4) }}
runAfter:
- suite-config
```
- Remove `- mcpi` from `post-install-verify` `runAfter` list (~line 484)
- Renumber section "16. Verify health..." back to "15." if sections were renumbered

#### `tekton/generate-tekton-tasks.yml`
Remove the MCPI block (~lines 45-52):
```yaml
# 3. Generate Tasks (MCPI)
# -------------------------------------------------------------------------
- name: Generate Tasks (MCPI)
ansible.builtin.template:
src: "{{ task_src_dir }}/mcpi/{{ item }}.yml.j2"
dest: "{{ task_target_dir }}/{{ item }}.yaml"
with_items:
- mcpi
```
Also renumber subsequent sections (AI Service was originally section 3, not 4).

#### `tekton/generate-tekton-pipelines.yml`
Remove the MCPI pipelines entry (~lines 46-47):
```yaml
# MCPI Pipelines
- mcpi-install
```

#### `python/src/mas/cli/__main__.py`
Remove:
- The usage text line: `" - <ForestGreen>mas-cli mcpi-install</ForestGreen> Install Maximo Cluster Performance Insights\n"`
- The dispatcher block (~lines 78-82):
```python
if function == "mcpi-install":
from mas.cli.mcpi.install.app import McpiInstallApp
app = McpiInstallApp()
raise SystemExit(app.install(argv[2:]))
```

#### `pytest.ini`
Remove the two MCPI markers (~lines 12-13):
```
mcpi-install: MCPI installation tests (mas-cli mcpi-install)
mcpi_install: MCPI installation tests (mas-cli mcpi-install)
```

#### `image/cli/mascli/mas`
Remove the `mcpi-install` case block (~lines 290-298):
```bash
mcpi-install)
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" >> $LOGFILE
echo "!! mcpi-install !!" >> $LOGFILE
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" >> $LOGFILE
# Take the first parameter off (it will be "mcpi-install")
shift
# Run the new Python-based mcpi-install
mas-cli mcpi-install "$@"
;;
```

#### `image/cli/app-root/src/.bashrc`
Remove the MCPI Management section (~lines 51-52):
```
echo "MCPI Management:"
echo " - ${TEXT_BOLD}${COLOR_GREEN}mas mcpi-install${TEXT_RESET} to install MCPI into an existing MAS instance"
```

#### `python-devops` repo: `src/mas/devops/tekton.py`
Remove:
- `prepareMcpiPipelinesNamespace()` function (~lines 846-920)
- `launchMcpiInstallPipeline()` function (~lines 1610-1628)

**Validation**: After all edits, run a grep to confirm no remaining `mcpi-install` or `mcpi_channel` references in shared files. Tekton generation playbooks should parse cleanly (no missing template references).

---

### Phase 3 — Add `--mcpi-channel` to `mas-cli install`

**Objective**: Implement MCPI as a standard MAS app option in the existing install command, following the same pattern as `facilities_channel`.

#### `python/src/mas/cli/install/argParser.py`
In the "MAS Applications" argument group (after `--aiservice-channel`, before the `# Arcgis` section), add:
```python
masAppsArgGroup.add_argument(
"--mcpi-channel",
required=False,
help="Subscription channel for Maximo Cluster Performance Insights",
)
```

#### `python/src/mas/cli/install/app.py` — `nonInteractiveMode()` init block
At lines ~2204-2216, `nonInteractiveMode()` initializes all install booleans to `False`. Add `self.installMcpi = False` to this block alongside the other flags.

#### `python/src/mas/cli/install/app.py` — `nonInteractiveMode()` key dispatch
After the `elif key == "aiservice_channel":` block (around line 2414), add:
```python
elif key == "mcpi_channel":
if value is not None and value != "":
self.setParam("mcpi_channel", value)
self.installMcpi = True
```

#### `python/src/mas/cli/install/app.py` — `configApps()`
After the AI Service block (end of method, around line 1356), add a simple unconditional prompt:
```python
self.installMcpi = self.yesOrNo("Install Maximo Cluster Performance Insights (MCPI)")
if self.installMcpi:
self.configAppChannel("mcpi") # OR: self.promptForString(...)
```

> **Note**: `McpiCfg` has no subscription channel field in the CR, but we still prompt for a channel to match the install pattern and for future use. If `configAppChannel` requires an entry in the compatibility matrix, use `promptForString("MCPI subscription channel", "mcpi_channel")` instead.

#### `python/src/mas/cli/install/params.py`
Add `"mcpi_channel"` to `optionalParams` list (near the app channels section).

#### `python/src/mas/cli/install/argBuilder.py` — `buildCommand()`
After the `if self.installAIService:` block (~line 285), add:
```python
if self.installMcpi:
command += f" --mcpi-channel \"{self.getParam('mcpi_channel')}\"{newline}"
```

#### `python/src/mas/cli/install/summarizer.py`
Add an `mcpiSummary()` method following the pattern of `facilitiesSummary()` or `assistSummary()`:
```python
def mcpiSummary(self) -> None:
if self.installMcpi:
self.printSummary("MCPI", self.getParam("mcpi_channel"))
else:
self.printSummary("MCPI", "Do Not Install")
```
Call `self.mcpiSummary()` in the appropriate place in the summary output method.

**Validation**: Run `python -m pytest python/tests -m unit -k install` to confirm existing install tests pass. Verify `--help` output for `mas-cli install` shows `--mcpi-channel`.

---

### Phase 4 — Final validation

**Objective**: Confirm the full state of all three repos is clean and correct.

[ ] **4.1** In `cli` repo: run `grep -r "mcpi-install\|McpiInstall\|mcpi_channel\|gencfg_mcpicfg\|launchMcpiInstall\|prepareMcpiPipelines" python/ tekton/ image/ pytest.ini` — expect zero results (except `mcpi_channel` in the new optionalParams and argParser additions)

[ ] **4.2** In `cli` repo: run `ansible-playbook tekton/generate-tekton-tasks.yml --check` — expect success (no missing template errors)

[ ] **4.3** In `cli` repo: run `ansible-playbook tekton/generate-tekton-pipelines.yml --check` — expect success

[ ] **4.4** In `cli` repo: run `.venv/bin/pytest python/tests -m unit` — all unit tests pass

[ ] **4.5** In `ansible-devops` repo: confirm `ibm/mas_devops/roles/gencfg_mcpicfg/` directory is gone

[ ] **4.6** In `python-devops` repo: run `.venv/bin/pytest test/` — all tests pass (mcpi test file removed, no broken imports)

---

## Final Validation

### Success criteria

1. `grep -r "mcpi-install" cli/python/ cli/tekton/ cli/image/` returns zero matches
2. `ansible-playbook tekton/generate-tekton-tasks.yml` completes without errors
3. `ansible-playbook tekton/generate-tekton-pipelines.yml` completes without errors
4. `mas-cli install --help` shows `--mcpi-channel` in the MAS Applications group
5. `mas-cli mcpi-install` returns "command not found" or usage error (no longer a valid subcommand)
6. All unit tests in `cli` repo pass
7. All tests in `python-devops` pass
8. `gencfg_mcpicfg` role no longer exists in `ansible-devops`

### Troubleshooting

- If `generate-tekton-tasks.yml` fails: check that `tekton/src/tasks/mcpi/` directory was fully removed and no `with_items: - mcpi` block remains
- If `generate-tekton-pipelines.yml` fails: check that `tekton/src/pipelines/mcpi-install.yml.j2` was removed and `all_pipelines` list no longer contains `mcpi-install`
- If Python import fails: ensure `python/src/mas/cli/mcpi/` directory was fully removed and `__main__.py` dispatcher was cleaned up
- If `installMcpi` attribute error: ensure `self.installMcpi = False` default is set in `InstallApp.__init__()` alongside other `self.installXxx = False` defaults
10 changes: 6 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ image/cli/mascli/fyre-dev.noble3.tgke-env.sh
image/cli/mascli/fyre-dev.noble3.tgke-db2u-manage-env.sh
image/cli/podman-build*

build/lib/mas/cli

python/.venv
python/.venv-windows
python/build
Expand All @@ -64,7 +66,7 @@ rbac-install.yaml

.venv
/.bob/notes
pytest.log
/dist
/.bob/.bob-errors
/.mkdocs_cache
pytest.log
/dist
/.bob/.bob-errors
/.mkdocs_cache
9 changes: 9 additions & 0 deletions python/src/mas/cli/install/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,10 @@ def configApps(self):
else:
self.installAIService = False

self.installMcpi = self.yesOrNo("Install Maximo Cluster Performance Insights (MCPI)")
if self.installMcpi:
self.promptForString("MCPI subscription channel", "mcpi_channel", validator=NotEmptyValidator())

@logMethodCall
def configAppChannel(self, appId):
versions = self.getCompatibleVersions(self.params["mas_channel"], appId)
Expand Down Expand Up @@ -2214,6 +2218,7 @@ def nonInteractiveMode(self) -> None:
self.db2SetAffinity = False
self.db2SetTolerations = False
self.installAIService = False
self.installMcpi = False
self.slsLicenseFileLocal = None
self.db2LicenseFileLocal = None
self.aiserviceTenantSchedulingConfigFileLocal = None
Expand Down Expand Up @@ -2385,6 +2390,10 @@ def nonInteractiveMode(self) -> None:
if value is not None and value != "":
self.setParam("mas_app_channel_facilities", value)
self.installFacilities = True
elif key == "mcpi_channel":
if value is not None and value != "":
self.setParam("mcpi_channel", value)
self.installMcpi = True
elif key == "aiservice_channel":
if value is not None and value != "":
self.setParam("aiservice_channel", value)
Expand Down
2 changes: 2 additions & 0 deletions python/src/mas/cli/install/argBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ def buildCommand(self) -> str:
command += f" --aiservice-channel \"{self.getParam('aiservice_channel')}\"{newline}"
if self.getParam("configure_aiassistant") != "":
command += f" --configure-aiassistant \"{self.getParam('configure_aiassistant')}\"{newline}"
if self.installMcpi:
command += f" --mcpi-channel \"{self.getParam('mcpi_channel')}\"{newline}"

# Arcgis
# -----------------------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions python/src/mas/cli/install/argParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,11 @@ def isValidFile(parser: argparse.ArgumentParser, arg: str) -> str:
required=False,
help="Subscription channel for Maximo AI Service",
)
masAppsArgGroup.add_argument(
"--mcpi-channel",
required=False,
help="Subscription channel for Maximo Cluster Performance Insights",
)

# Arcgis
# -----------------------------------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions python/src/mas/cli/install/summarizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class InstallSummarizerMixin:
installOptimizer: bool
installFacilities: bool
installAIService: bool
installMcpi: bool
installArcgis: bool
dynamicClient: DynamicClient
applyPreInstallMASRBAC: bool
Expand Down Expand Up @@ -461,6 +462,12 @@ def aiServiceSummary(self) -> None:
self.printParamSummary("URL", "aiservice_watsonxai_url")
self.printParamSummary("Project ID", "aiservice_watsonxai_project_id")

def mcpiSummary(self) -> None:
if self.installMcpi:
self.printSummary("Maximo Cluster Performance Insights (MCPI)", self.getParam("mcpi_channel"))
else:
self.printSummary("Maximo Cluster Performance Insights (MCPI)", "Do Not Install")

def db2Summary(self) -> None:
if (
self.getParam("db2_action_system") == "install"
Expand Down Expand Up @@ -666,6 +673,7 @@ def displayInstallSummary(self) -> None:
self.inspectionSummary()
self.facilitiesSummary()
self.aiServiceSummary()
self.mcpiSummary()

# Application Dependencies
self.mongoSummary()
Expand Down
Loading
Loading