Repository: rook/rook
Pull request #15541 (2025-03-18 16:44:58)

ci: Install csi-op in integration tests
<!-- Thank you for contributing to Rook! -->

<!-- STEPS TO FOLLOW:
  1. Add a description of the changes (frequently the same as the commit description)
  2. Enter the issue number next to "Resolves #" below (if there is no tracking issue resolved, **remove that section**)
  3. Review our Contributing documentation at https://rook.io/docs/rook/latest/Contributing/development-flow/
  4. Follow the steps in the checklist below, starting with the **Commit Message Formatting**.
-->

<!-- Uncomment this section with the issue number if an issue is being resolved
**Issue resolved by this Pull Request:**
Resolves #
--->

**Checklist:**

- [ ] **Commit Message Formatting**: Commit titles and messages follow guidelines in the [developer guide](https://rook.io/docs/rook/latest/Contributing/development-flow/#commit-structure).
- [ ] Reviewed the developer guide on [Submitting a Pull Request](https://rook.io/docs/rook/latest/Contributing/development-flow/#submitting-a-pull-request)
- [ ] [Pending release notes](https://github.com/rook/rook/blob/master/PendingReleaseNotes.md) updated with breaking and/or notable changes for the next minor release.
- [ ] Documentation has been updated, if necessary.
- [ ] Unit tests have been added, if necessary.
- [ ] Integration tests have been added, if necessary.



Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index fe6a08f53..b83cca118 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -71,7 +71,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        go-version: ["1.23", "1.24"]
+        go-version: ["1.22", "1.23"]
     steps:
       - name: checkout
         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -84,7 +84,7 @@ jobs:
           go-version: ${{ matrix.go-version }}
 
       - name: set up QEMU
-        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # master
+        uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # master
         with:
           platforms: all
 
diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml
index 1928bc859..a853988a7 100644
--- a/.github/workflows/golangci-lint.yaml
+++ b/.github/workflows/golangci-lint.yaml
@@ -31,7 +31,7 @@ jobs:
         with:
           go-version: "1.23"
       - name: golangci-lint
-        uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1
+        uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0
         with:
           # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
           version: v1.62
diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml
index 970163609..db72d3c18 100644
--- a/.github/workflows/linters.yaml
+++ b/.github/workflows/linters.yaml
@@ -61,4 +61,4 @@ jobs:
         run: make pylint
 
       - name: Setup black for py
-        uses: psf/black@8a737e727ac5ab2f1d4cf5876720ed276dc8dc4b # stable
+        uses: psf/black@1b2427a2b785cc4aac97c19bb4b9a0de063f9547 # stable
diff --git a/.github/workflows/push-build.yaml b/.github/workflows/push-build.yaml
index af1581f39..25c9dc10c 100644
--- a/.github/workflows/push-build.yaml
+++ b/.github/workflows/push-build.yaml
@@ -14,7 +14,6 @@ defaults:
 
 permissions:
   contents: read
-  packages: write
 
 jobs:
   push-image-to-container-registry:
@@ -32,7 +31,7 @@ jobs:
 
         # docker/setup-qemu action installs QEMU static binaries, which are used to run builders for architectures other than the host.
       - name: set up QEMU
-        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # master
+        uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # master
         with:
           platforms: all
 
@@ -42,20 +41,6 @@ jobs:
           username: ${{ secrets.DOCKER_USERNAME }}
           password: ${{ secrets.DOCKER_PASSWORD }}
 
-      - name: Login to Quay.io
-        uses: docker/login-action@v3
-        with:
-          registry: quay.io
-          username: ${{ secrets.QUAY_USERNAME }}
-          password: ${{ secrets.QUAY_ROBOT_TOKEN }}
-
-      - name: Login to GitHub Container Registry
-        uses: docker/login-action@v3
-        with:
-          registry: ghcr.io
-          username: ${{ github.actor }}
-          password: ${{ secrets.GITHUB_TOKEN }}
-
       - name: Configure AWS Credentials
         uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
         with:
@@ -69,10 +54,6 @@ jobs:
           echo "BRANCH_NAME=${GITHUB_REF##*/}" >> $GITHUB_ENV
           echo "GITHUB_REF"=${GITHUB_REF} >> $GITHUB_ENV
 
-      - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
-        with:
-          python-version: 3.13
-
       - name: Install dependencies
         run: |
           python3 -m pip install --upgrade pip setuptools wheel
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index b2ef65031..91f0accb6 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -64,6 +64,6 @@ jobs:
       # Upload the results to GitHub's code scanning dashboard (optional).
       # Commenting out will disable upload of results to your repo's Code Scanning dashboard
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11
+        uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
         with:
           sarif_file: results.sarif
diff --git a/Documentation/CRDs/Cluster/ceph-cluster-crd.md b/Documentation/CRDs/Cluster/ceph-cluster-crd.md
index eea150e38..51b4e4fc1 100755
--- a/Documentation/CRDs/Cluster/ceph-cluster-crd.md
+++ b/Documentation/CRDs/Cluster/ceph-cluster-crd.md
@@ -150,13 +150,6 @@ A specific will contain a specific release of Ceph as well as security fixes fro
 * `failureDomainLabel`: The label that is expected on each node where the mons
     are expected to be deployed. The labels must be found in the list of
     well-known [topology labels](#osd-topology).
-* `externalMonIDs`: ID list of external mons deployed outside of Rook cluster
-    and not managed by Rook. If set, Rook will not remove external mons from quorum
-    and populate external mons addresses to mon endpoints for CSI.
-    This parameter is supported only for local Rook cluster running in normal mode,
-    meaning that it will be ignored for external cluster (`spec.external.enabled: true`)
-    or for `stretchedCluster`.
-    For more details see [external mons](../../Storage-Configuration/Advanced/ceph-mon-health.md#external-monitors).
 * `zones`: The failure domain names where the Mons are expected to be deployed.
     There must be **at least three zones** specified in the list. Each zone can be
     backed by a different storage class by specifying the `volumeClaimTemplate`.
diff --git a/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md b/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md
index f04c71013..cd8839836 100644
--- a/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md
+++ b/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md
@@ -390,10 +390,6 @@ spec:
       debug_rgw: "10" # int
       # debug-rgw: "20" # equivalent config keys can have dashes or underscores
       rgw_s3_auth_use_ldap: "true" # bool
-    rgwConfigFromSecret:
-      rgw_keystone_barbican_password: # name of rgw option with secret value
-        name: "barbican-secret" # name of K8s secret 
-        key: "password" # key of secret value in K8s secret.Data map[string]string
     rgwCommandFlags:
       rgw_dmclock_auth_res: "100.0" # float
       rgw_d4n_l1_datacache_persistent_path: /var/log/rook/rgwd4ncache # string
@@ -401,13 +397,12 @@ spec:
 ```
 
 * `rgwConfig` - These configurations are applied and modified at runtime, without RGW restart.
-* `rgwConfigFromSecret` - same as `rgwConfig` but config value is referenced from k8s secret.
 * `rgwCommandFlags` - These configurations are applied as CLI arguments and result in RGW daemons
     restarting when updates are applied. Restarts are desired behavior for some RGW configs.
 
 !!! note
-    Once an `rgwConfig` or `rgwConfigFromSecret` is set, it will not be removed from Ceph's central config store when removed
-    from the `rgwConfig` or `rgwConfigFromSecret` spec. Be sure to specifically set values back to their defaults once done.
+    Once an `rgwConfig` is set, it will not be removed from Ceph's central config store when removed
+    from the `rgwConfig` spec. Be sure to specifically set values back to their defaults once done.
     With this in mind, `rgwCommandFlags` may be a better choice for temporary config values like
     debug levels.
 
@@ -460,34 +455,6 @@ data:
     "bindpass.secret": aGVsbG8ud29ybGQK # hello.world
 ```
 
-### Example - usage with `rgwConfigFromSecret`
-
-The sample configuration below demonstrates how to securely handle secret configuration parameters when setting up RGW for [Barbican integration](https://docs.ceph.com/en/latest/radosgw/config-ref/#barbican-settings).
-
-```yaml
-  # ...
-  gateway:
-    # ...
-    rgwConfig:
-      rgw_barbican_url: "http://barbican.example.com:9311"
-      rgw_keystone_barbican_domain: "domain"
-      rgw_keystone_barbican_project: "project" 
-      rgw_keystone_barbican_user: "user"
-    rgwConfigFromSecret:
-      rgw_keystone_barbican_password:
-        name: "barbican-secret"
-        key: "password"
----
-apiVersion: v1
-kind: Secret
-metadata:
-  name: barbican-secret
-  namespace: rook-ceph
-type: Opaque
-data:
-  "password": aGVsbG8ud29ybGQK # hello.world
-```
-
 ## Deleting a CephObjectStore
 
 During deletion of a CephObjectStore resource, Rook protects against accidental or premature
diff --git a/Documentation/CRDs/specification.md b/Documentation/CRDs/specification.md
index 781234732..99e2000fd 100644
--- a/Documentation/CRDs/specification.md
+++ b/Documentation/CRDs/specification.md
@@ -7203,23 +7203,6 @@ applied. Use with caution.</p>
 </tr>
 <tr>
 <td>
-<code>rgwConfigFromSecret</code><br/>
-<em>
-<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secretkeyselector-v1-core">
-map[string]k8s.io/api/core/v1.SecretKeySelector
-</a>
-</em>
-</td>
-<td>
-<em>(Optional)</em>
-<p>RgwConfigFromSecret works exactly like RgwConfig but takes config value from Secret Key reference.
-Values are modified at runtime without RGW restart.
-This feature is intended for advanced users. It allows breaking configurations to be easily
-applied. Use with caution.</p>
-</td>
-</tr>
-<tr>
-<td>
 <code>rgwCommandFlags</code><br/>
 <em>
 map[string]string
@@ -8794,22 +8777,6 @@ VolumeClaimTemplate
 <p>VolumeClaimTemplate is the PVC definition</p>
 </td>
 </tr>
-<tr>
-<td>
-<code>externalMonIDs</code><br/>
-<em>
-[]string
-</em>
-</td>
-<td>
-<em>(Optional)</em>
-<p>ExternalMonIDs - optional list of monitor IDs which are deployed externally and not managed by Rook.
-If set, Rook will not remove mons with given IDs from quorum.
-This parameter is used only for local Rook cluster running in normal mode
-and will be ignored if external or stretched mode is used.
-leading</p>
-</td>
-</tr>
 </tbody>
 </table>
 <h3 id="ceph.rook.io/v1.MonZoneSpec">MonZoneSpec
diff --git a/Documentation/Contributing/development-flow.md b/Documentation/Contributing/development-flow.md
index b3418016a..30d519d99 100644
--- a/Documentation/Contributing/development-flow.md
+++ b/Documentation/Contributing/development-flow.md
@@ -279,7 +279,7 @@ See the action details for an ssh connection to the Github runner.
 
 ## Commit structure
 
-Rook maintainers value clear and detailed commit messages.
+Rook maintainers value clear, lengthy and explanatory commit messages.
 
 Requirements for commits:
 
diff --git a/Documentation/Helm-Charts/operator-chart.md b/Documentation/Helm-Charts/operator-chart.md
index ace2f972d..4307fc083 100644
--- a/Documentation/Helm-Charts/operator-chart.md
+++ b/Documentation/Helm-Charts/operator-chart.md
@@ -60,13 +60,13 @@ The following table lists the configurable parameters of the rook-operator chart
 | `csi.cephFSPluginUpdateStrategy` | CSI CephFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate | `RollingUpdate` |
 | `csi.cephFSPluginUpdateStrategyMaxUnavailable` | A maxUnavailable parameter of CSI cephFS plugin daemonset update strategy. | `1` |
 | `csi.cephcsi.repository` | Ceph CSI image repository | `"quay.io/cephcsi/cephcsi"` |
-| `csi.cephcsi.tag` | Ceph CSI image tag | `"v3.13.1"` |
+| `csi.cephcsi.tag` | Ceph CSI image tag | `"v3.13.0"` |
 | `csi.cephfsLivenessMetricsPort` | CSI CephFS driver metrics port | `9081` |
 | `csi.cephfsPodLabels` | Labels to add to the CSI CephFS Deployments and DaemonSets Pods | `nil` |
 | `csi.clusterName` | Cluster name identifier to set as metadata on the CephFS subvolume and RBD images. This will be useful in cases like for example, when two container orchestrator clusters (Kubernetes/OCP) are using a single ceph cluster | `nil` |
 | `csi.csiAddons.enabled` | Enable CSIAddons | `false` |
 | `csi.csiAddons.repository` | CSIAddons sidecar image repository | `"quay.io/csiaddons/k8s-sidecar"` |
-| `csi.csiAddons.tag` | CSIAddons sidecar image tag | `"v0.12.0"` |
+| `csi.csiAddons.tag` | CSIAddons sidecar image tag | `"v0.11.0"` |
 | `csi.csiAddonsCephFSProvisionerPort` | CSI Addons server port for the Ceph FS provisioner | `9070` |
 | `csi.csiAddonsPort` | CSI Addons server port | `9070` |
 | `csi.csiAddonsRBDProvisionerPort` | CSI Addons server port for the RBD provisioner | `9070` |
diff --git a/Documentation/Storage-Configuration/Advanced/ceph-mon-health.md b/Documentation/Storage-Configuration/Advanced/ceph-mon-health.md
index 5e69b9ac2..f39c931b3 100644
--- a/Documentation/Storage-Configuration/Advanced/ceph-mon-health.md
+++ b/Documentation/Storage-Configuration/Advanced/ceph-mon-health.md
@@ -124,43 +124,3 @@ CephCluster CR:
 - `spec.network.hostNetwork`: When enabled or disabled, Rook fails over all monitors, configuring them to enable or disable host networking.
 - `spec.network.Provider` : When updated from being empty to "host", Rook fails over all monitors, configuring them to enable or disable host networking.
 - `spec.network.multiClusterService`: When enabled or disabled, Rook fails over all monitors, configuring them to start (or stop) using service IPs compatible with the multi-cluster service.
-
-## External Monitors
-
-!!! attention
-    This feature is experimental.
-
-It is possible to have both Rook-managed and external monitors in the same Rook cluster.
-One use case for this is 2 datacenter aka 2-AZ (Availability Zone) setup. For 2-AZ setup, Zone outage will lead to loss of the k8s control plane and half of the worker nodes hosting Rook mons.
-In this case remaining half of the Rook cluster will not be able to form quorum and will be in a stuck state even if the other half of worker nodes are still up.
-To avoid this situation, external mons can be used to form quorum and keep the cluster running.
-
-If there are external monitors, Rook must be aware of them, otherwise Rook will remove the unknown mons from the quorum. This is done by setting the `mon.externalMonIDs` field in the CephCluster CR. The `mon.count` ignores the number of `mon.externalMonIDs`. For example, if `mon.count = 2`, Rook will create two internal mons no matter how many external mons are in the cluster and no matter what their health state might be. External monitors are supported only for the local Rook cluster running in normal mode. The external mons will be ignored for external clusters and stretch clusters.
-
-Here is a step-by-step guide on how to add external monitors to a Rook cluster:
-
-1. Create a CephCluster CR with the `mon.externalMonIDs` field set to the external monitor IDs. For example:
-
-    ```yaml
-    spec:
-      mon:
-        # Spawn 2 Mons - one Mon in each AZ managed by Rook
-        count: 2
-        allowMultiplePerNode: false
-        # ID of external Mon
-        externalMonIDs:
-        - ext-mon-1 
-    ```
-
-    This will tell Rook to create two internal monitors in the cluster and to keep the external monitor with the ID `ext-mon-1` if it is found in the quorum.
-    It is also possible to add `externalMonIDs` to an existing Cluster.
-2. Wait until the Rook cluster and internal mons are up and running.
-3. Manually deploy an external monitor with the ID `ext-mon-1` outside of the Rook cluster and its availability zones. See [ceph guide](https://docs.ceph.com/en/latest/rados/operations/add-or-rm-mons/#adding-removing-monitors) on deploying monitors.
-4. Move the external Mon to [disallow-mode](https://docs.ceph.com/en/reef/rados/operations/change-mon-elections/#rados-operations-disallow-mode) to make sure that it won't be elected as a leader. The purpose of external mode is maintaining quorum to elect a new leader in case of a zone outage. The external Mon will likely have higher latency to the cluster so it should not be elected.
-5. Check that the external monitor is in the quorum by running `ceph status` or `ceph quorum_status` from the toolbox.
-6. Check that the external mon is added to the Rook mon endpoints:
-
-    ```console
-    $ kubectl -n rook-ceph get cm rook-ceph-mon-endpoints -o jsonpath='{.data.data}'
-    a=10.100.68.61:6789,b=10.103.201.172:6789,ext-mon-1=10.102.136.102:6789
-    ```
diff --git a/Documentation/Storage-Configuration/Advanced/ceph-osd-mgmt.md b/Documentation/Storage-Configuration/Advanced/ceph-osd-mgmt.md
index 668e55674..25a7abf7d 100644
--- a/Documentation/Storage-Configuration/Advanced/ceph-osd-mgmt.md
+++ b/Documentation/Storage-Configuration/Advanced/ceph-osd-mgmt.md
@@ -24,7 +24,7 @@ ceph osd utilization
 ```
 
 ```console
-kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- bash
+kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') bash
 ```
 
 ## Add an OSD
diff --git a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md
index 013a4885b..17ca0d0ac 100644
--- a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md
+++ b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md
@@ -166,9 +166,9 @@ that the controller inspects and forwards to one or more CSI-Addons sidecars for
 Deploy the controller by running the following commands:
 
 ```console
-kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.12.0/crds.yaml
-kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.12.0/rbac.yaml
-kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.12.0/setup-controller.yaml
+kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.11.0/crds.yaml
+kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.11.0/rbac.yaml
+kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.11.0/setup-controller.yaml
 ```
 
 This creates the required CRDs and configures permissions.
@@ -196,31 +196,31 @@ Execute the following to enable the CSI-Addons sidecars:
 CSI-Addons supports the following operations:
 
 * Reclaim Space
-    * [Creating a ReclaimSpaceJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/reclaimspace.md#reclaimspacejob)
-    * [Creating a ReclaimSpaceCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/reclaimspace.md#reclaimspacecronjob)
-    * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/reclaimspace.md#annotating-perstentvolumeclaims)
-    * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/reclaimspace.md#annotating-namespace)
-    * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/reclaimspace.md#annotating-storageclass)
+    * [Creating a ReclaimSpaceJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/reclaimspace.md#reclaimspacejob)
+    * [Creating a ReclaimSpaceCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/reclaimspace.md#reclaimspacecronjob)
+    * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/reclaimspace.md#annotating-perstentvolumeclaims)
+    * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/reclaimspace.md#annotating-namespace)
+    * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/reclaimspace.md#annotating-storageclass)
 * Network Fencing
-    * [Creating a NetworkFence](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/networkfence.md)
+    * [Creating a NetworkFence](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/networkfence.md)
 * Volume Replication
-    * [Creating VolumeReplicationClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/volumereplicationclass.md)
-    * [Creating VolumeReplication CR](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/volumereplication.md)
+    * [Creating VolumeReplicationClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/volumereplicationclass.md)
+    * [Creating VolumeReplication CR](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/volumereplication.md)
 * Key Rotation Job for PV encryption
-    * [Creating EncryptionKeyRotationJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/encryptionkeyrotation.md#encryptionkeyrotationjob)
-    * [Creating EncryptionKeyRotationCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/encryptionkeyrotation.md#encryptionkeyrotationcronjob)
-    * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/encryptionkeyrotation.md#annotating-persistentvolumeclaims)
-    * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/encryptionkeyrotation.md#annotating-namespace)
-    * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.12.0/docs/encryptionkeyrotation.md#annotating-storageclass)
+    * [Creating EncryptionKeyRotationJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/encryptionkeyrotation.md#encryptionkeyrotationjob)
+    * [Creating EncryptionKeyRotationCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/encryptionkeyrotation.md#encryptionkeyrotationcronjob)
+    * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/encryptionkeyrotation.md#annotating-persistentvolumeclaims)
+    * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/encryptionkeyrotation.md#annotating-namespace)
+    * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.11.0/docs/encryptionkeyrotation.md#annotating-storageclass)
 
 ## Enable RBD and CephFS Encryption Support
 
 Ceph-CSI supports encrypting PersistentVolumeClaims (PVCs) for both RBD and CephFS.
 This can be achieved using LUKS for RBD and fscrypt for CephFS. More details on encrypting RBD PVCs can be found
-[here](https://github.com/ceph/ceph-csi/blob/v3.13.1/docs/deploy-rbd.md#encryption-for-rbd-volumes),
+[here](https://github.com/ceph/ceph-csi/blob/v3.13.0/docs/deploy-rbd.md#encryption-for-rbd-volumes),
 which includes a full list of supported encryption configurations.
-More details on encrypting CephFS PVCs can be found [here](https://github.com/ceph/ceph-csi/blob/v3.13.1/docs/deploy-cephfs.md#cephfs-volume-encryption).
-A sample KMS configmap can be found [here](https://github.com/ceph/ceph-csi/blob/v3.13.1/examples/kms/vault/kms-config.yaml).
+More details on encrypting CephFS PVCs can be found [here](https://github.com/ceph/ceph-csi/blob/v3.13.0/docs/deploy-cephfs.md#cephfs-volume-encryption).
+A sample KMS configmap can be found [here](https://github.com/ceph/ceph-csi/blob/v3.13.0/examples/kms/vault/kms-config.yaml).
 
 !!! note
     Not all KMS are compatible with fscrypt. Generally, KMS that either store secrets to use directly (like Vault)
diff --git a/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md b/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md
index 1acb2f816..88b5b6840 100644
--- a/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md
+++ b/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md
@@ -18,13 +18,13 @@ kubectl -n $ROOK_OPERATOR_NAMESPACE edit configmap rook-ceph-operator-config
 The default upstream images are included below, which you can change to your desired images.
 
 ```yaml
-ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.13.1"
+ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.13.0"
 ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0"
 ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.1.0"
 ROOK_CSI_ATTACHER_IMAGE: "registry.k8s.io/sig-storage/csi-attacher:v4.8.0"
 ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.13.1"
 ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.k8s.io/sig-storage/csi-snapshotter:v8.2.0"
-ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.12.0"
+ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.11.0"
 ```
 
 ### **Use private repository**
diff --git a/Documentation/Troubleshooting/ceph-common-issues.md b/Documentation/Troubleshooting/ceph-common-issues.md
index 599002ef0..8cca5195b 100644
--- a/Documentation/Troubleshooting/ceph-common-issues.md
+++ b/Documentation/Troubleshooting/ceph-common-issues.md
@@ -99,7 +99,7 @@ After you verify the basic health of the running pods, next you will want to run
 The [rook-ceph-tools pod](ceph-toolbox.md) provides a simple environment to run Ceph tools. Once the pod is up and running, connect to the pod to execute Ceph commands to evaluate that current state of the cluster.
 
 ```console
-kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[*].metadata.name}') -- bash
+kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[*].metadata.name}') bash
 ```
 
 #### Ceph Commands
diff --git a/Documentation/Troubleshooting/direct-tools.md b/Documentation/Troubleshooting/direct-tools.md
index 0053b5e29..1ff3a92c2 100644
--- a/Documentation/Troubleshooting/direct-tools.md
+++ b/Documentation/Troubleshooting/direct-tools.md
@@ -19,7 +19,7 @@ After the pod is started, connect to it like this:
 
 ```console
 kubectl -n rook-ceph get pod -l app=rook-direct-mount
-$ kubectl -n rook-ceph exec -it <pod> -- bash
+$ kubectl -n rook-ceph exec -it <pod> bash
 ```
 
 ## Block Storage Tools
diff --git a/PendingReleaseNotes.md b/PendingReleaseNotes.md
index faf45c2b6..252f70b28 100644
--- a/PendingReleaseNotes.md
+++ b/PendingReleaseNotes.md
@@ -13,5 +13,3 @@ Object:
     See https://github.com/rook/rook/pull/15376 for more information.
 
 ## Features
-
-- Support external mons for local Rook cluster (see [#14733](https://github.com/rook/rook/issues/14733)).
diff --git a/build/makelib/golang.mk b/build/makelib/golang.mk
index 5d9dacd11..fdef2670c 100644
--- a/build/makelib/golang.mk
+++ b/build/makelib/golang.mk
@@ -48,7 +48,7 @@ GO_TEST_FLAGS ?=
 # ====================================================================================
 # Setup go environment
 
-GO_SUPPORTED_VERSIONS ?= 1.23|1.24
+GO_SUPPORTED_VERSIONS ?= 1.22|1.23
 
 GO_PACKAGES := $(foreach t,$(GO_SUBDIRS),$(GO_PROJECT)/$(t)/...)
 GO_INTEGRATION_TEST_PACKAGES := $(foreach t,$(GO_INTEGRATION_TESTS_SUBDIRS),$(GO_PROJECT)/$(t)/integration)
diff --git a/build/release/Makefile b/build/release/Makefile
index efb068736..e8b592306 100644
--- a/build/release/Makefile
+++ b/build/release/Makefile
@@ -66,10 +66,8 @@ FLAVORS ?= output
 override BRANCH_NAME := pr/$(BRANCH_NAME)
 endif
 
-DOCKER_REGISTRY ?= docker.io/rook
-QUAY_REGISTRY ?= quay.io/rook
-GHCR_REGISTRY ?= ghcr.io/rook
-REGISTRIES ?= $(DOCKER_REGISTRY) $(QUAY_REGISTRY) $(GHCR_REGISTRY)
+DOCKER_REGISTRY ?= rook
+REGISTRIES ?= $(DOCKER_REGISTRY)
 IMAGE_ARCHS := $(subst linux_,,$(filter linux_%,$(PLATFORMS)))
 IMAGE_PLATFORMS := $(subst _,/,$(subst $(SPACE),$(COMMA),$(filter linux_%,$(PLATFORMS))))
 IMAGE_PLATFORMS_COMMA := $(shell echo "$(IMAGE_PLATFORMS)" | sed 's/ /,/g' | sed 's/.$$//')
@@ -193,14 +191,10 @@ $(foreach r,$(REGISTRIES), $(foreach i,$(IMAGES), $(foreach a,$(IMAGE_ARCHS),$(e
 
 publish.manifest.image.%: publish.all.images $(MANIFEST_TOOL)
 	$(MANIFEST_TOOL) push from-args --platforms $(IMAGE_PLATFORMS_COMMA) --template $(DOCKER_REGISTRY)/$*-ARCH:$(VERSION) --target $(DOCKER_REGISTRY)/$*:$(VERSION)
-	$(MANIFEST_TOOL) push from-args --platforms $(IMAGE_PLATFORMS_COMMA) --template $(QUAY_REGISTRY)/$*-ARCH:$(VERSION) --target $(QUAY_REGISTRY)/$*:$(VERSION)
-	$(MANIFEST_TOOL) push from-args --platforms $(IMAGE_PLATFORMS_COMMA) --template $(GHCR_REGISTRY)/$*-ARCH:$(VERSION) --target $(GHCR_REGISTRY)/$*:$(VERSION)
 
 # add the "master" tag to the master image, but do not add the "release" tag for the release channel
 promote.manifest.image.%: promote.all.images $(MANIFEST_TOOL)
 	[ "$(CHANNEL)" = "release" ] || $(MANIFEST_TOOL) push from-args --platforms $(IMAGE_PLATFORMS_COMMA) --template $(DOCKER_REGISTRY)/$*-ARCH:$(VERSION) --target $(DOCKER_REGISTRY)/$*:$(CHANNEL)
-	[ "$(CHANNEL)" = "release" ] || $(MANIFEST_TOOL) push from-args --platforms $(IMAGE_PLATFORMS_COMMA) --template $(QUAY_REGISTRY)/$*-ARCH:$(VERSION) --target $(QUAY_REGISTRY)/$*:$(CHANNEL)
-	[ "$(CHANNEL)" = "release" ] || $(MANIFEST_TOOL) push from-args --platforms $(IMAGE_PLATFORMS_COMMA) --template $(GHCR_REGISTRY)/$*-ARCH:$(VERSION) --target $(GHCR_REGISTRY)/$*:$(CHANNEL)
 
 build.images: build.all.images
 publish.images: $(addprefix publish.manifest.image.,$(IMAGES))
diff --git a/cmd/rook/ceph/mgr.go b/cmd/rook/ceph/mgr.go
index 8b8834de1..372beb449 100644
--- a/cmd/rook/ceph/mgr.go
+++ b/cmd/rook/ceph/mgr.go
@@ -79,7 +79,7 @@ func runMgrSidecar(cmd *cobra.Command, args []string) error {
 	}
 
 	context := createContext()
-	clusterInfo.InternalMonitors = opcontroller.ParseMonEndpoints(cfg.monEndpoints)
+	clusterInfo.Monitors = opcontroller.ParseMonEndpoints(cfg.monEndpoints)
 	rook.LogStartupInfo(mgrSidecarCmd.Flags())
 
 	ownerRef := opcontroller.ClusterOwnerRef(clusterName, ownerRefID)
diff --git a/cmd/rook/ceph/osd.go b/cmd/rook/ceph/osd.go
index c231c4b95..d4f0caf5f 100644
--- a/cmd/rook/ceph/osd.go
+++ b/cmd/rook/ceph/osd.go
@@ -344,7 +344,7 @@ func commonOSDInit(cmd *cobra.Command) {
 	rook.SetLogLevel()
 	rook.LogStartupInfo(cmd.Flags())
 
-	clusterInfo.InternalMonitors = opcontroller.ParseMonEndpoints(cfg.monEndpoints)
+	clusterInfo.Monitors = opcontroller.ParseMonEndpoints(cfg.monEndpoints)
 }
 
 // use zone/region/hostname labels in the crushmap
diff --git a/deploy/charts/rook-ceph/templates/resources.yaml b/deploy/charts/rook-ceph/templates/resources.yaml
index d09b83f03..53a806f02 100644
--- a/deploy/charts/rook-ceph/templates/resources.yaml
+++ b/deploy/charts/rook-ceph/templates/resources.yaml
@@ -1789,16 +1789,6 @@ spec:
                       maximum: 9
                       minimum: 0
                       type: integer
-                    externalMonIDs:
-                      description: |-
-                        ExternalMonIDs - optional list of monitor IDs which are deployed externally and not managed by Rook.
-                        If set, Rook will not remove mons with given IDs from quorum.
-                        This parameter is used only for local Rook cluster running in normal mode
-                        and will be ignored if external or stretched mode is used.
-                        leading
-                      items:
-                        type: string
-                      type: array
                     failureDomainLabel:
                       type: string
                     stretchCluster:
@@ -11963,36 +11953,6 @@ spec:
                         applied. Use with caution.
                       nullable: true
                       type: object
-                    rgwConfigFromSecret:
-                      additionalProperties:
-                        description: SecretKeySelector selects a key of a Secret.
-                        properties:
-                          key:
-                            description: The key of the secret to select from.  Must be a valid secret key.
-                            type: string
-                          name:
-                            default: ""
-                            description: |-
-                              Name of the referent.
-                              This field is effectively required, but due to backwards compatibility is
-                              allowed to be empty. Instances of this type with an empty value here are
-                              almost certainly wrong.
-                              More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
-                            type: string
-                          optional:
-                            description: Specify whether the Secret or its key must be defined
-                            type: boolean
-                        required:
-                          - key
-                        type: object
-                        x-kubernetes-map-type: atomic
-                      description: |-
-                        RgwConfigFromSecret works exactly like RgwConfig but takes config value from Secret Key reference.
-                        Values are modified at runtime without RGW restart.
-                        This feature is intended for advanced users. It allows breaking configurations to be easily
-                        applied. Use with caution.
-                      nullable: true
-                      type: object
                     securePort:
                       description: The port the rgw service will be listening on (https)
                       format: int32
diff --git a/deploy/charts/rook-ceph/values.yaml b/deploy/charts/rook-ceph/values.yaml
index b16cf0061..4ce764357 100644
--- a/deploy/charts/rook-ceph/values.yaml
+++ b/deploy/charts/rook-ceph/values.yaml
@@ -489,7 +489,7 @@ csi:
     # -- Ceph CSI image repository
     repository: quay.io/cephcsi/cephcsi
     # -- Ceph CSI image tag
-    tag: v3.13.1
+    tag: v3.13.0
 
   registrar:
     # -- Kubernetes CSI registrar image repository
@@ -539,7 +539,7 @@ csi:
     # -- CSIAddons sidecar image repository
     repository: quay.io/csiaddons/k8s-sidecar
     # -- CSIAddons sidecar image tag
-    tag: v0.12.0
+    tag: v0.11.0
 
   nfs:
     # -- Enable the nfs csi driver
diff --git a/deploy/examples/crds.yaml b/deploy/examples/crds.yaml
index 3f206e8b2..25b576af4 100644
--- a/deploy/examples/crds.yaml
+++ b/deploy/examples/crds.yaml
@@ -1787,16 +1787,6 @@ spec:
                       maximum: 9
                       minimum: 0
                       type: integer
-                    externalMonIDs:
-                      description: |-
-                        ExternalMonIDs - optional list of monitor IDs which are deployed externally and not managed by Rook.
-                        If set, Rook will not remove mons with given IDs from quorum.
-                        This parameter is used only for local Rook cluster running in normal mode
-                        and will be ignored if external or stretched mode is used.
-                        leading
-                      items:
-                        type: string
-                      type: array
                     failureDomainLabel:
                       type: string
                     stretchCluster:
@@ -11954,36 +11944,6 @@ spec:
                         applied. Use with caution.
                       nullable: true
                       type: object
-                    rgwConfigFromSecret:
-                      additionalProperties:
-                        description: SecretKeySelector selects a key of a Secret.
-                        properties:
-                          key:
-                            description: The key of the secret to select from.  Must be a valid secret key.
-                            type: string
-                          name:
-                            default: ""
-                            description: |-
-                              Name of the referent.
-                              This field is effectively required, but due to backwards compatibility is
-                              allowed to be empty. Instances of this type with an empty value here are
-                              almost certainly wrong.
-                              More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
-                            type: string
-                          optional:
-                            description: Specify whether the Secret or its key must be defined
-                            type: boolean
-                        required:
-                          - key
-                        type: object
-                        x-kubernetes-map-type: atomic
-                      description: |-
-                        RgwConfigFromSecret works exactly like RgwConfig but takes config value from Secret Key reference.
-                        Values are modified at runtime without RGW restart.
-                        This feature is intended for advanced users. It allows breaking configurations to be easily
-                        applied. Use with caution.
-                      nullable: true
-                      type: object
                     securePort:
                       description: The port the rgw service will be listening on (https)
                       format: int32
diff --git a/deploy/examples/create-external-cluster-resources.py b/deploy/examples/create-external-cluster-resources.py
index a2f84eb50..38a567d8d 100644
--- a/deploy/examples/create-external-cluster-resources.py
+++ b/deploy/examples/create-external-cluster-resources.py
@@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
-        http://www.apache.org/licenses/LICENSE-2.0
+	http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/deploy/examples/images.txt b/deploy/examples/images.txt
index 5e90e4a7f..53cf473bf 100644
--- a/deploy/examples/images.txt
+++ b/deploy/examples/images.txt
@@ -2,8 +2,8 @@
  gcr.io/k8s-staging-sig-storage/objectstorage-sidecar:v20240513-v0.1.0-35-gefb3255
  quay.io/ceph/ceph:v19.2.1
  quay.io/ceph/cosi:v0.1.2
- quay.io/cephcsi/cephcsi:v3.13.1
- quay.io/csiaddons/k8s-sidecar:v0.12.0
+ quay.io/cephcsi/cephcsi:v3.13.0
+ quay.io/csiaddons/k8s-sidecar:v0.11.0
  registry.k8s.io/sig-storage/csi-attacher:v4.8.0
  registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0
  registry.k8s.io/sig-storage/csi-provisioner:v5.1.0
diff --git a/deploy/examples/operator-openshift.yaml b/deploy/examples/operator-openshift.yaml
index df7758060..26eead857 100644
--- a/deploy/examples/operator-openshift.yaml
+++ b/deploy/examples/operator-openshift.yaml
@@ -189,7 +189,7 @@ data:
   # The default version of CSI supported by Rook will be started. To change the version
   # of the CSI driver to something other than what is officially supported, change
   # these images to the desired release of the CSI driver.
-  # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.13.1"
+  # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.13.0"
   # ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0"
   # ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.13.1"
   # ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.1.0"
@@ -556,7 +556,7 @@ data:
   CSI_ENABLE_CSIADDONS: "false"
   # Enable watch for faster recovery from rbd rwo node loss
   ROOK_WATCH_FOR_NODE_FAILURE: "true"
-  # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.12.0"
+  # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.11.0"
   # The GCSI RPC timeout value (in seconds). It should be >= 120. If this variable is not set or is an invalid value, it's default to 150.
   CSI_GRPC_TIMEOUT_SECONDS: "150"
 
diff --git a/deploy/examples/operator.yaml b/deploy/examples/operator.yaml
index 043d5c87b..b1fcd62b3 100644
--- a/deploy/examples/operator.yaml
+++ b/deploy/examples/operator.yaml
@@ -119,7 +119,7 @@ data:
   # The default version of CSI supported by Rook will be started. To change the version
   # of the CSI driver to something other than what is officially supported, change
   # these images to the desired release of the CSI driver.
-  # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.13.1"
+  # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.13.0"
   # ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0"
   # ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.13.1"
   # ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.1.0"
@@ -511,7 +511,7 @@ data:
   CSI_ENABLE_CSIADDONS: "false"
   # Enable watch for faster recovery from rbd rwo node loss
   ROOK_WATCH_FOR_NODE_FAILURE: "true"
-  # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.12.0"
+  # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.11.0"
   # The CSI GRPC timeout value (in seconds). It should be >= 120. If this variable is not set or is an invalid value, it's default to 150.
   CSI_GRPC_TIMEOUT_SECONDS: "150"
 
diff --git a/go.mod b/go.mod
index e2560fa22..9f0e2076b 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
 	github.com/ceph/ceph-csi/api v0.0.0-20241216133622-88b7e0d6684f
 	github.com/ceph/go-ceph v0.32.0
 	github.com/coreos/pkg v0.0.0-20240122114842-bbd7aa9bf6fb
-	github.com/csi-addons/kubernetes-csi-addons v0.12.0
+	github.com/csi-addons/kubernetes-csi-addons v0.11.0
 	github.com/gemalto/kmip-go v0.0.10
 	github.com/go-ini/ini v1.67.0
 	github.com/google/go-cmp v0.7.0
@@ -32,8 +32,8 @@ require (
 	github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20221122204822-d1a8c34382f1
 	github.com/libopenstorage/secrets v0.0.0-20240416031220-a17cf7f72c6c
 	github.com/pkg/errors v0.9.1
-	github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.81.0
-	github.com/prometheus-operator/prometheus-operator/pkg/client v0.81.0
+	github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.80.1
+	github.com/prometheus-operator/prometheus-operator/pkg/client v0.80.1
 	github.com/rook/rook/pkg/apis v0.0.0-20241216163035-3170ac6a0c58
 	github.com/sethvargo/go-password v0.3.1
 	github.com/spf13/cobra v1.9.1
@@ -42,17 +42,17 @@ require (
 	github.com/sykesm/zap-logfmt v0.0.4
 	go.uber.org/automaxprocs v1.6.0
 	go.uber.org/zap v1.27.0
-	golang.org/x/sync v0.12.0
+	golang.org/x/sync v0.11.0
 	gopkg.in/ini.v1 v1.67.0
 	gopkg.in/yaml.v2 v2.4.0
-	k8s.io/api v0.32.3
-	k8s.io/apiextensions-apiserver v0.32.3
-	k8s.io/apimachinery v0.32.3
-	k8s.io/cli-runtime v0.32.3
-	k8s.io/client-go v0.32.3
-	k8s.io/cloud-provider v0.32.3
+	k8s.io/api v0.32.1
+	k8s.io/apiextensions-apiserver v0.32.1
+	k8s.io/apimachinery v0.32.1
+	k8s.io/cli-runtime v0.32.1
+	k8s.io/client-go v0.32.1
+	k8s.io/cloud-provider v0.32.1
 	k8s.io/utils v0.0.0-20241210054802-24370beab758
-	sigs.k8s.io/controller-runtime v0.20.3
+	sigs.k8s.io/controller-runtime v0.20.1
 	sigs.k8s.io/mcs-api v0.1.0
 	sigs.k8s.io/yaml v1.4.0
 )
@@ -80,7 +80,7 @@ require (
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/emicklei/go-restful/v3 v3.12.1 // indirect
 	github.com/evanphx/json-patch v5.9.0+incompatible // indirect
-	github.com/evanphx/json-patch/v5 v5.9.11 // indirect
+	github.com/evanphx/json-patch/v5 v5.9.0 // indirect
 	github.com/fsnotify/fsnotify v1.7.0 // indirect
 	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
 	github.com/gemalto/flume v0.13.1 // indirect
@@ -146,15 +146,15 @@ require (
 	github.com/x448/float16 v0.8.4 // indirect
 	github.com/xlab/treeprint v1.2.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
-	golang.org/x/crypto v0.35.0 // indirect
-	golang.org/x/net v0.36.0 // indirect
+	golang.org/x/crypto v0.32.0 // indirect
+	golang.org/x/net v0.34.0 // indirect
 	golang.org/x/oauth2 v0.25.0 // indirect
-	golang.org/x/sys v0.30.0 // indirect
-	golang.org/x/term v0.29.0 // indirect
-	golang.org/x/text v0.22.0 // indirect
+	golang.org/x/sys v0.29.0 // indirect
+	golang.org/x/term v0.28.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	golang.org/x/time v0.9.0 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
-	google.golang.org/protobuf v1.36.5 // indirect
+	google.golang.org/protobuf v1.36.3 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
@@ -163,7 +163,7 @@ require (
 	sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
 	sigs.k8s.io/kustomize/api v0.18.0 // indirect
 	sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
-	sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
 )
 
 exclude (
diff --git a/go.sum b/go.sum
index 94d5136ad..f92a4e581 100644
--- a/go.sum
+++ b/go.sum
@@ -252,8 +252,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
 github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-github.com/csi-addons/kubernetes-csi-addons v0.12.0 h1:RbF2dCjWV4ljynibEOkA0wbwwt/09awjOKgEFC14Bns=
-github.com/csi-addons/kubernetes-csi-addons v0.12.0/go.mod h1:8vrXJUZrlI2ms2aZ6qRfp8ieRlpHEefTX5azOFi67o0=
+github.com/csi-addons/kubernetes-csi-addons v0.11.0 h1:0f6AIXcpu68Vj0Q1IKij1l6arJfKFiaTZ9GwHuvLm/o=
+github.com/csi-addons/kubernetes-csi-addons v0.11.0/go.mod h1:HJd3znD4i5D92/2PKqzrwBg5Q7Ur2me20VYakdBHzpk=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -297,8 +297,8 @@ github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
 github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
 github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
-github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
-github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
+github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
+github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
@@ -764,8 +764,8 @@ github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8Ay
 github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
 github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
 github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
-github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
-github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
+github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
+github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -780,8 +780,8 @@ github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ
 github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
 github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
 github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
-github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
-github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
+github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
+github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
 github.com/openshift/api v0.0.0-20210105115604-44119421ec6b/go.mod h1:aqU5Cq+kqKKPbDMqxo9FojgDeSpNJI7iuskjXjtojDg=
 github.com/openshift/api v0.0.0-20241216151652-de9de05a8e43 h1:3lcB5nqOOfsJzY4JD12AMKyg3+yQhAdJzNDenbmbMQg=
 github.com/openshift/api v0.0.0-20241216151652-de9de05a8e43/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo=
@@ -819,11 +819,11 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4
 github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
 github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.44.1/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg=
 github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.46.0/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg=
-github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.81.0 h1:mSii7z+TihzdeULnGjLnNikgtDbeViY/wW8s3430rhE=
-github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.81.0/go.mod h1:YfnEQzw7tUQa0Sjiz8V6QFc6JUGE+i5wybsjc3EOKn8=
+github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.80.1 h1:DP+PUNVOc+Bkft8a4QunLzaZ0RspWuD3tBbcPHr2PeE=
+github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.80.1/go.mod h1:6x4x0t9BP35g4XcjkHE9EB3RxhyfxpdpmZKd/Qyk8+M=
 github.com/prometheus-operator/prometheus-operator/pkg/client v0.46.0/go.mod h1:k4BrWlVQQsvBiTcDnKEMgyh/euRxyxgrHdur/ZX/sdA=
-github.com/prometheus-operator/prometheus-operator/pkg/client v0.81.0 h1:z8ETgiD2hThJi3+3S8eKAbC9/pwPq1kGt8HkeGlDstw=
-github.com/prometheus-operator/prometheus-operator/pkg/client v0.81.0/go.mod h1:EKK9z5OIxxwaCZmgaidiIfvy6mF7x8M3AJHmxwx+QB4=
+github.com/prometheus-operator/prometheus-operator/pkg/client v0.80.1 h1:7/TPlTy7tkMXC1KwS2WdUdU8J220DszlSQ1+KHjXwHc=
+github.com/prometheus-operator/prometheus-operator/pkg/client v0.80.1/go.mod h1:0lW4yp2XE7AKohpGB2UGdomjP08rbr4f8JwAN6sUDWU=
 github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
@@ -1021,8 +1021,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
 golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
 golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
-golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
+golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
+golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1133,8 +1133,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
-golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
-golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
+golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1171,8 +1171,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
-golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
+golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1277,8 +1277,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
-golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1291,8 +1291,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
-golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
+golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1310,8 +1310,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1579,8 +1579,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
-google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
+google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1645,15 +1645,15 @@ k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
 k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
 k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8=
 k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg=
-k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
-k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
+k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
+k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
 k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
 k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
 k8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE=
 k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
 k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
-k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
-k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
+k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw=
+k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto=
 k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
 k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
 k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
@@ -1665,14 +1665,14 @@ k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRp
 k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
 k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
 k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
-k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
-k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
+k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
 k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
 k8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw=
 k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
 k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
-k8s.io/cli-runtime v0.32.3 h1:khLF2ivU2T6Q77H97atx3REY9tXiA3OLOjWJxUrdvss=
-k8s.io/cli-runtime v0.32.3/go.mod h1:vZT6dZq7mZAca53rwUfdFSZjdtLyfF61mkf/8q+Xjak=
+k8s.io/cli-runtime v0.32.1 h1:19nwZPlYGJPUDbhAxDIS2/oydCikvKMHsxroKNGA2mM=
+k8s.io/cli-runtime v0.32.1/go.mod h1:NJPbeadVFnV2E7B7vF+FvU09mpwYlZCu8PqjzfuOnkY=
 k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
 k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
 k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
@@ -1681,10 +1681,10 @@ k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA=
 k8s.io/client-go v0.20.0/go.mod h1:4KWh/g+Ocd8KkCwKF8vUNnmqgv+EVnQDK4MBF4oB5tY=
 k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
 k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4=
-k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
-k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
-k8s.io/cloud-provider v0.32.3 h1:WC7KhWrqXsU4b0E4tjS+nBectGiJbr1wuc1TpWXvtZM=
-k8s.io/cloud-provider v0.32.3/go.mod h1:/fwBfgRPuh16n8vLHT+PPT+Bc4LAEaJYj38opO2wsYY=
+k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
+k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
+k8s.io/cloud-provider v0.32.1 h1:74rRhnfca3o4CsjjnIp/C3ARVuSmyNsxgWPtH0yc9Z0=
+k8s.io/cloud-provider v0.32.1/go.mod h1:GECSanFT+EeZ/ToX3xlasjETzMUI+VFu92zHUDUsGHw=
 k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
 k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
 k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
@@ -1739,8 +1739,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 sigs.k8s.io/controller-runtime v0.2.2/go.mod h1:9dyohw3ZtoXQuV1e766PHUn+cmrRCIcBh6XIMFNMZ+I=
 sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
-sigs.k8s.io/controller-runtime v0.20.3 h1:I6Ln8JfQjHH7JbtCD2HCYHoIzajoRxPNuvhvcDbZgkI=
-sigs.k8s.io/controller-runtime v0.20.3/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
+sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE=
+sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU=
 sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
 sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
 sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
@@ -1753,16 +1753,14 @@ sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt
 sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo=
 sigs.k8s.io/mcs-api v0.1.0 h1:edDbg0oRGfXw8TmZjKYep06LcJLv/qcYLidejnUp0PM=
 sigs.k8s.io/mcs-api v0.1.0/go.mod h1:gGiAryeFNB4GBsq2LBmVqSgKoobLxt+p7ii/WG5QYYw=
-sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 h1:kXv6kKdoEtedwuqMmkqhbkgvYKeycVbC8+iPCP9j5kQ=
-sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
-sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
-sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
 sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/pkg/apis/ceph.rook.io/v1/types.go b/pkg/apis/ceph.rook.io/v1/types.go
index 538526634..de8c70cce 100755
--- a/pkg/apis/ceph.rook.io/v1/types.go
+++ b/pkg/apis/ceph.rook.io/v1/types.go
@@ -626,13 +626,6 @@ type MonSpec struct {
 	// +kubebuilder:pruning:PreserveUnknownFields
 	// +optional
 	VolumeClaimTemplate *VolumeClaimTemplate `json:"volumeClaimTemplate,omitempty"`
-	// ExternalMonIDs - optional list of monitor IDs which are deployed externally and not managed by Rook.
-	// If set, Rook will not remove mons with given IDs from quorum.
-	// This parameter is used only for local Rook cluster running in normal mode
-	// and will be ignored if external or stretched mode is used.
-	// leading
-	// +optional
-	ExternalMonIDs []string `json:"externalMonIDs,omitempty"`
 }
 
 // VolumeClaimTemplate is a simplified version of K8s corev1's PVC. It has no type meta or status.
@@ -1755,14 +1748,6 @@ type GatewaySpec struct {
 	// +optional
 	RgwConfig map[string]string `json:"rgwConfig,omitempty"`
 
-	// RgwConfigFromSecret works exactly like RgwConfig but takes config value from Secret Key reference.
-	// Values are modified at runtime without RGW restart.
-	// This feature is intended for advanced users. It allows breaking configurations to be easily
-	// applied. Use with caution.
-	// +nullable
-	// +optional
-	RgwConfigFromSecret map[string]v1.SecretKeySelector `json:"rgwConfigFromSecret,omitempty"`
-
 	// RgwCommandFlags sets Ceph RGW config values for the gateway clients that serve this object
 	// store. Values are modified at RGW startup, resulting in RGW pod restarts.
 	// This feature is intended for advanced users. It allows breaking configurations to be easily
diff --git a/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go b/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go
index b3ef8a9a4..90d36b973 100644
--- a/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go
+++ b/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go
@@ -2743,13 +2743,6 @@ func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) {
 			(*out)[key] = val
 		}
 	}
-	if in.RgwConfigFromSecret != nil {
-		in, out := &in.RgwConfigFromSecret, &out.RgwConfigFromSecret
-		*out = make(map[string]corev1.SecretKeySelector, len(*in))
-		for key, val := range *in {
-			(*out)[key] = *val.DeepCopy()
-		}
-	}
 	if in.RgwCommandFlags != nil {
 		in, out := &in.RgwCommandFlags, &out.RgwCommandFlags
 		*out = make(map[string]string, len(*in))
@@ -3353,11 +3346,6 @@ func (in *MonSpec) DeepCopyInto(out *MonSpec) {
 		*out = new(VolumeClaimTemplate)
 		(*in).DeepCopyInto(*out)
 	}
-	if in.ExternalMonIDs != nil {
-		in, out := &in.ExternalMonIDs, &out.ExternalMonIDs
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
 	return
 }
 
diff --git a/pkg/apis/go.mod b/pkg/apis/go.mod
index 06fad64c1..93888c7e0 100644
--- a/pkg/apis/go.mod
+++ b/pkg/apis/go.mod
@@ -22,8 +22,8 @@ require (
 	github.com/openshift/api v0.0.0-20241216151652-de9de05a8e43
 	github.com/pkg/errors v0.9.1
 	github.com/stretchr/testify v1.10.0
-	k8s.io/api v0.32.3
-	k8s.io/apimachinery v0.32.3
+	k8s.io/api v0.32.1
+	k8s.io/apimachinery v0.32.1
 )
 
 require (
@@ -63,30 +63,28 @@ require (
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
-	github.com/onsi/ginkgo/v2 v2.22.0 // indirect
-	github.com/onsi/gomega v1.36.1 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 	github.com/ryanuber/go-glob v1.0.0 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/spf13/pflag v1.0.6 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
-	golang.org/x/crypto v0.35.0 // indirect
-	golang.org/x/net v0.36.0 // indirect
+	golang.org/x/crypto v0.32.0 // indirect
+	golang.org/x/net v0.34.0 // indirect
 	golang.org/x/oauth2 v0.25.0 // indirect
-	golang.org/x/sys v0.30.0 // indirect
-	golang.org/x/term v0.29.0 // indirect
-	golang.org/x/text v0.22.0 // indirect
+	golang.org/x/sys v0.29.0 // indirect
+	golang.org/x/term v0.28.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	golang.org/x/time v0.9.0 // indirect
-	google.golang.org/protobuf v1.36.5 // indirect
+	google.golang.org/protobuf v1.36.3 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/client-go v0.32.3 // indirect
+	k8s.io/client-go v0.32.1 // indirect
 	k8s.io/klog/v2 v2.130.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
 	k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
 	sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
-	sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
 	sigs.k8s.io/yaml v1.4.0 // indirect
 )
 
diff --git a/pkg/apis/go.sum b/pkg/apis/go.sum
index a9d2e0666..a9c792c87 100644
--- a/pkg/apis/go.sum
+++ b/pkg/apis/go.sum
@@ -607,8 +607,8 @@ github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8Ay
 github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
 github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
 github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
-github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
-github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
+github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
+github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -622,8 +622,8 @@ github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ
 github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
 github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
 github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
-github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
-github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
+github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
+github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
 github.com/openshift/api v0.0.0-20210105115604-44119421ec6b/go.mod h1:aqU5Cq+kqKKPbDMqxo9FojgDeSpNJI7iuskjXjtojDg=
 github.com/openshift/api v0.0.0-20241216151652-de9de05a8e43 h1:3lcB5nqOOfsJzY4JD12AMKyg3+yQhAdJzNDenbmbMQg=
 github.com/openshift/api v0.0.0-20241216151652-de9de05a8e43/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo=
@@ -806,8 +806,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
 golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
 golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
-golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
+golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
+golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -917,8 +917,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
-golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
-golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
+golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1054,8 +1054,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
-golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1068,8 +1068,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
-golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
+golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1087,8 +1087,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1348,8 +1348,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
-google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
+google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1405,8 +1405,8 @@ k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
 k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
 k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8=
 k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg=
-k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
-k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
+k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
+k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
 k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
 k8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE=
 k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
@@ -1419,8 +1419,8 @@ k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRp
 k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
 k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
 k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
-k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
-k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
+k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
 k8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw=
 k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
 k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
@@ -1429,8 +1429,8 @@ k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA=
 k8s.io/client-go v0.20.0/go.mod h1:4KWh/g+Ocd8KkCwKF8vUNnmqgv+EVnQDK4MBF4oB5tY=
 k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
 k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4=
-k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
-k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
+k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
+k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
 k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
 k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk=
 k8s.io/code-generator v0.20.0/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
@@ -1482,16 +1482,14 @@ sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNza
 sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
-sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 h1:kXv6kKdoEtedwuqMmkqhbkgvYKeycVbC8+iPCP9j5kQ=
-sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
-sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
-sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
 sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/pkg/daemon/ceph/client/command.go b/pkg/daemon/ceph/client/command.go
index a7cfcbd95..ffc38fd02 100644
--- a/pkg/daemon/ceph/client/command.go
+++ b/pkg/daemon/ceph/client/command.go
@@ -212,7 +212,7 @@ func (c *CephToolCommand) run() ([]byte, error) {
 				err = errors.Errorf("%s", err.Error())
 			}
 			if stderr != "" {
-				err = errors.Errorf("err=%s: stderr=%s", err.Error(), stderr)
+				err = errors.Errorf("%s", stderr)
 			}
 		} else if c.timeout == 0 {
 			output, err = c.context.Executor.ExecuteCommandWithOutput(command, args...)
diff --git a/pkg/daemon/ceph/client/config.go b/pkg/daemon/ceph/client/config.go
index 278c37445..f2cc6119b 100644
--- a/pkg/daemon/ceph/client/config.go
+++ b/pkg/daemon/ceph/client/config.go
@@ -249,7 +249,7 @@ func PopulateMonHostMembers(clusterInfo *ClusterInfo) ([]string, []string) {
 	var monMembers []string
 	var monHosts []string
 
-	for _, monitor := range clusterInfo.AllMonitors() {
+	for _, monitor := range clusterInfo.Monitors {
 		if monitor.OutOfQuorum {
 			logger.Warningf("skipping adding mon %q to config file, detected out of quorum", monitor.Name)
 			continue
diff --git a/pkg/daemon/ceph/client/info.go b/pkg/daemon/ceph/client/info.go
index 79d273471..70e49bc48 100644
--- a/pkg/daemon/ceph/client/info.go
+++ b/pkg/daemon/ceph/client/info.go
@@ -39,13 +39,10 @@ type ClusterInfo struct {
 	FSID          string
 	MonitorSecret string
 	CephCred      CephCred
-	// InternalMonitors - montiros managed by Rook or external monitors when Rook manages external cluster.
-	InternalMonitors map[string]*MonInfo
-	// ExternalMons - external montiros listed in CephCluster.spec.mon.externalMonIDs when Rook managing local cluster.
-	ExternalMons map[string]*MonInfo
-	CephVersion  cephver.CephVersion
-	Namespace    string
-	OwnerInfo    *k8sutil.OwnerInfo
+	Monitors      map[string]*MonInfo
+	CephVersion   cephver.CephVersion
+	Namespace     string
+	OwnerInfo     *k8sutil.OwnerInfo
 	// Hide the name of the cluster since in 99% of uses we want to use the cluster namespace.
 	// If the CR name is needed, access it through the NamespacedName() method.
 	name              string
@@ -62,20 +59,6 @@ type ClusterInfo struct {
 	Context context.Context
 }
 
-func (c *ClusterInfo) AllMonitors() map[string]*MonInfo {
-	if len(c.ExternalMons) == 0 {
-		return c.InternalMonitors
-	}
-	res := make(map[string]*MonInfo, len(c.InternalMonitors)+len(c.ExternalMons))
-	for id, mon := range c.InternalMonitors {
-		res[id] = mon
-	}
-	for id, mon := range c.ExternalMons {
-		res[id] = mon
-	}
-	return res
-}
-
 // MonInfo is a collection of information about a Ceph mon.
 type MonInfo struct {
 	Name     string `json:"name"`
diff --git a/pkg/daemon/ceph/client/mirror.go b/pkg/daemon/ceph/client/mirror.go
index a0795c892..d9c2dc8a8 100644
--- a/pkg/daemon/ceph/client/mirror.go
+++ b/pkg/daemon/ceph/client/mirror.go
@@ -441,7 +441,7 @@ func CreateRBDMirrorBootstrapPeerWithoutPool(context *clusterd.Context, clusterI
 	logger.Infof("successfully created rbd-mirror bootstrap peer token for cluster %q", clusterInfo.NamespacedName().Name)
 
 	mons := sets.New[string]()
-	for _, mon := range clusterInfo.AllMonitors() {
+	for _, mon := range clusterInfo.Monitors {
 		mons.Insert(mon.Endpoint)
 	}
 
diff --git a/pkg/operator/ceph/cluster/cluster_external.go b/pkg/operator/ceph/cluster/cluster_external.go
index 9045c9906..37f825263 100644
--- a/pkg/operator/ceph/cluster/cluster_external.go
+++ b/pkg/operator/ceph/cluster/cluster_external.go
@@ -109,7 +109,7 @@ func (c *ClusterController) configureExternalCephCluster(cluster *cluster) error
 	}
 
 	// update the msgr2 flag
-	for _, m := range cluster.ClusterInfo.InternalMonitors {
+	for _, m := range cluster.ClusterInfo.Monitors {
 		// m.Endpoint=10.1.115.104:3300
 		monPort := util.GetPortFromEndpoint(m.Endpoint)
 		if monPort == client.Msgr2port {
@@ -123,7 +123,7 @@ func (c *ClusterController) configureExternalCephCluster(cluster *cluster) error
 	}
 
 	// Save CSI configmap
-	monEndpoints := csi.MonEndpoints(cluster.ClusterInfo.InternalMonitors, cluster.Spec.RequireMsgr2())
+	monEndpoints := csi.MonEndpoints(cluster.ClusterInfo.Monitors, cluster.Spec.RequireMsgr2())
 	csiConfigEntry := &csi.CSIClusterConfigEntry{
 		Namespace: cluster.ClusterInfo.Namespace,
 		ClusterInfo: cephcsi.ClusterInfo{
@@ -176,18 +176,6 @@ func (c *ClusterController) configureExternalCephCluster(cluster *cluster) error
 		}
 	}
 
-	if csi.EnableCSIOperator() {
-		logger.Info("create cephConnection and defaultClientProfile for external mode")
-		err = csi.CreateUpdateCephConnection(c.context.Client, cluster.ClusterInfo, *cluster.Spec)
-		if err != nil {
-			return errors.Wrap(err, "failed to create/update cephConnection")
-		}
-		err = csi.CreateDefaultClientProfile(c.context.Client, cluster.ClusterInfo, cluster.ClusterInfo.NamespacedName())
-		if err != nil {
-			return errors.Wrap(err, "failed to create/update default client profile")
-		}
-	}
-
 	// We don't update the connection status since it is done by the health go routine
 	return nil
 }
diff --git a/pkg/operator/ceph/cluster/mon/health.go b/pkg/operator/ceph/cluster/mon/health.go
index fe1042ae8..050d88f43 100644
--- a/pkg/operator/ceph/cluster/mon/health.go
+++ b/pkg/operator/ceph/cluster/mon/health.go
@@ -1,4 +1,5 @@
-/* Copyright 2018 The Rook Authors. All rights reserved.
+/*
+Copyright 2018 The Rook Authors. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,7 +20,6 @@ import (
 	"context"
 	"fmt"
 	"os"
-	"slices"
 	"strings"
 	"time"
 
@@ -202,12 +202,6 @@ func (c *Cluster) checkHealth(ctx context.Context) error {
 	}
 	logger.Debugf("Mon quorum status: %+v", quorumStatus)
 
-	// handle external Mons
-	quorumStatus, err = c.reconcileExternalMons(ctx, quorumStatus)
-	if err != nil {
-		return errors.Wrap(err, "failed to check external mons health")
-	}
-
 	// Use a local mon count in case the user updates the crd in another goroutine.
 	// We need to complete a health check with a consistent value.
 	desiredMonCount := c.spec.Mon.Count
@@ -215,7 +209,7 @@ func (c *Cluster) checkHealth(ctx context.Context) error {
 
 	// Source of truth of which mons should exist is our *clusterInfo*
 	monsNotFound := map[string]interface{}{}
-	for _, mon := range c.ClusterInfo.InternalMonitors {
+	for _, mon := range c.ClusterInfo.Monitors {
 		monsNotFound[mon.Name] = struct{}{}
 	}
 
@@ -320,7 +314,7 @@ func (c *Cluster) checkHealth(ctx context.Context) error {
 	// handle all mons that haven't been in the Ceph mon map
 	for mon := range monsNotFound {
 		logger.Warningf("mon %s NOT found in ceph mon map, failover", mon)
-		c.failMon(len(c.ClusterInfo.InternalMonitors), desiredMonCount, mon)
+		c.failMon(len(c.ClusterInfo.Monitors), desiredMonCount, mon)
 		// only deal with one "not found in ceph mon map" mon per health check
 		return nil
 	}
@@ -357,24 +351,24 @@ func (c *Cluster) checkHealth(ctx context.Context) error {
 
 	// failover mon if `multiClusterService` is enabled but mon service is not exported
 	if allMonsInQuorum && c.spec.Network.MultiClusterService.Enabled {
-		for _, mon := range c.ClusterInfo.InternalMonitors {
+		for _, mon := range c.ClusterInfo.Monitors {
 			monResourceName := resourceName(mon.Name)
 			isAlreadyExported, err := k8sutil.IsServiceExported(c.ClusterInfo.Context, c.context, monResourceName, c.ClusterInfo.Namespace)
 			if err != nil {
 				return errors.Wrapf(err, "failed to check if the service %q is already exported", mon.Name)
 			}
 			if !isAlreadyExported {
-				c.failMon(len(c.ClusterInfo.InternalMonitors), desiredMonCount, mon.Name)
+				c.failMon(len(c.ClusterInfo.Monitors), desiredMonCount, mon.Name)
 				return nil
 			}
 		}
 	}
 
 	// failover any mons present in the mon fail over list
-	for _, mon := range c.ClusterInfo.InternalMonitors {
+	for _, mon := range c.ClusterInfo.Monitors {
 		if c.monsToFailover.Has(mon.Name) {
 			logger.Infof("fail over mon %q from the mon fail over list", mon.Name)
-			c.failMon(len(c.ClusterInfo.InternalMonitors), desiredMonCount, mon.Name)
+			c.failMon(len(c.ClusterInfo.Monitors), desiredMonCount, mon.Name)
 			c.monsToFailover.Delete(mon.Name)
 			return nil
 		}
@@ -383,102 +377,12 @@ func (c *Cluster) checkHealth(ctx context.Context) error {
 	return nil
 }
 
-// reconcileExternalMons handling external monitors defined in CephCluster.spec.mon.externalMonIDs when Rook managing local cluster.
-func (c *Cluster) reconcileExternalMons(ctx context.Context, quorumStatus cephclient.MonStatusResponse) (cephclient.MonStatusResponse, error) {
-	if len(c.spec.Mon.ExternalMonIDs) != 0 {
-		if c.spec.External.Enable {
-			logger.Warning("ignore external mon IDs in cluster spec: cluster is running in external mode")
-			return quorumStatus, nil
-		}
-		if c.spec.IsStretchCluster() {
-			logger.Warning("ignore external mon IDs in cluster spec: cluster is running in stretch mode")
-			return quorumStatus, nil
-		}
-	}
-
-	extMonIDs := c.spec.Mon.ExternalMonIDs
-	if c.ClusterInfo.ExternalMons == nil {
-		c.ClusterInfo.ExternalMons = make(map[string]*cephclient.MonInfo, len(extMonIDs))
-	}
-
-	extMonsChanged := false
-	for extID := range c.ClusterInfo.ExternalMons {
-		if slices.Contains(extMonIDs, extID) {
-			continue
-		}
-		// existing external mon was removed from Cluster CRD spec:
-		// remove it from CLusterInfo
-		logger.Debugf("existing external mon %q was removed from spec: removing it", extID)
-		delete(c.ClusterInfo.ExternalMons, extID)
-		extMonsChanged = true
-	}
-
-	// handle external monitors if configured in cluster CRD:
-	logger.Debugf("external mon IDs: %v", extMonIDs)
-	for _, extID := range extMonIDs {
-		monStatus, inQuorum := getMonByID(extID, quorumStatus)
-		if inQuorum {
-			logger.Debugf("external mon %q in quorum", extID)
-		} else {
-			logger.Debugf("external mon %q not in quorum %+v, %+v", extID, quorumStatus.Quorum, quorumStatus.MonMap.Mons)
-		}
-		_, inInfo := c.ClusterInfo.ExternalMons[extID]
-		if inQuorum && !inInfo {
-			// add newly discovered external mon to cluster info:
-			monInfo := monStatusToInfo(monStatus)
-			c.ClusterInfo.ExternalMons[extID] = monInfo
-			extMonsChanged = true
-			logger.Infof("new external mon %q found: %s, adding it", extID, monInfo.Endpoint)
-		} else if !inQuorum && inInfo {
-			// remove external mon from cluster info if it is out of quorum:
-			delete(c.ClusterInfo.ExternalMons, extID)
-			extMonsChanged = true
-			logger.Infof("new external mon %q not in quorum: removing it", extID)
-		}
-	}
-	if extMonsChanged {
-		// update config if external mon was removed or added:
-		if err := c.saveMonConfig(); err != nil {
-			return cephclient.MonStatusResponse{}, errors.Wrap(err, "failed to save mon config after adding/removing external mon")
-		}
-	}
-
-	// now, remove processed external mons from ceph quorum status response
-	// to not affect existing logic processing internal mons that are within the mon.count
-	quorumStatus = removeMonsFromQuorumStatusResponse(quorumStatus, extMonIDs)
-	return quorumStatus, nil
-}
-
-func removeMonsFromQuorumStatusResponse(quorumStatus cephclient.MonStatusResponse, idsToRemove []string) cephclient.MonStatusResponse {
-	var removeFromQuorum []int
-	var keepMons []cephclient.MonMapEntry
-
-	for _, mon := range quorumStatus.MonMap.Mons {
-		if !slices.Contains(idsToRemove, mon.Name) {
-			keepMons = append(keepMons, mon)
-			continue
-		}
-		removeFromQuorum = append(removeFromQuorum, mon.Rank)
-	}
-
-	var keepQuorum []int
-	for _, rank := range quorumStatus.Quorum {
-		if slices.Contains(removeFromQuorum, rank) {
-			continue
-		}
-		keepQuorum = append(keepQuorum, rank)
-	}
-	quorumStatus.MonMap.Mons = keepMons
-	quorumStatus.Quorum = keepQuorum
-	return quorumStatus
-}
-
 func (c *Cluster) trackMonInOrOutOfQuorum(monName string, inQuorum bool) (bool, error) {
 	updateNeeded := false
 	var monsOutOfQuorum []string
 	if monName == "" {
 		// All mons are in quorum, so make sure no mons are marked out of quorum
-		for monName, mon := range c.ClusterInfo.InternalMonitors {
+		for monName, mon := range c.ClusterInfo.Monitors {
 			if mon.OutOfQuorum {
 				logger.Infof("resetting mon %q to be back in quorum", monName)
 				mon.OutOfQuorum = false
@@ -486,7 +390,7 @@ func (c *Cluster) trackMonInOrOutOfQuorum(monName string, inQuorum bool) (bool,
 			}
 		}
 	} else {
-		mon, ok := c.ClusterInfo.InternalMonitors[monName]
+		mon, ok := c.ClusterInfo.Monitors[monName]
 		if !ok {
 			logger.Infof("mon %q not found to keep track of being out of quorum", monName)
 			return false, nil
@@ -771,7 +675,7 @@ func (c *Cluster) failoverMon(name string) error {
 			m.PublicIP = monService.Spec.ClusterIP
 		}
 	}
-	c.ClusterInfo.InternalMonitors[m.DaemonName] = cephclient.NewMonInfo(m.DaemonName, m.PublicIP, m.Port)
+	c.ClusterInfo.Monitors[m.DaemonName] = cephclient.NewMonInfo(m.DaemonName, m.PublicIP, m.Port)
 
 	// Start the deployment
 	newMonMightBeInQuorum = true
@@ -813,7 +717,7 @@ func (c *Cluster) removeMonWithOptionalQuorum(daemonName string, shouldRemoveFro
 			logger.Errorf("failed to remove mon %q from quorum. %v", daemonName, err)
 		}
 	}
-	delete(c.ClusterInfo.InternalMonitors, daemonName)
+	delete(c.ClusterInfo.Monitors, daemonName)
 	delete(c.mapping.Schedule, daemonName)
 
 	if err := c.saveMonConfig(); err != nil {
@@ -909,9 +813,9 @@ func (c *Cluster) addOrRemoveExternalMonitor(status cephclient.MonStatusResponse
 	// clearing the content of clusterinfo monitors
 	// and populate oldClusterInfoMonitors with monitors from clusterinfo
 	// later c.ClusterInfo.Monitors get populated again
-	for monName, mon := range c.ClusterInfo.InternalMonitors {
+	for monName, mon := range c.ClusterInfo.Monitors {
 		oldClusterInfoMonitors[mon.Name] = mon
-		delete(c.ClusterInfo.InternalMonitors, monName)
+		delete(c.ClusterInfo.Monitors, monName)
 	}
 	logger.Debugf("ClusterInfo is now Empty, refilling it from status.MonMap.Mons")
 
@@ -927,9 +831,17 @@ func (c *Cluster) addOrRemoveExternalMonitor(status cephclient.MonStatusResponse
 		if _, ok := oldClusterInfoMonitors[mon.Name]; !ok {
 			// If the mon is part of the quorum
 			if inQuorum {
-				info := monStatusToInfo(mon)
-				logger.Infof("new external mon %q found: %s, adding it", mon.Name, info.Endpoint)
-				c.ClusterInfo.InternalMonitors[mon.Name] = info
+				// let's add it to ClusterInfo
+				// FYI mon.PublicAddr is "10.97.171.131:6789/0"
+				// so we need to remove '/0'
+				endpointSlash := strings.Split(mon.PublicAddr, "/")
+				endpoint := endpointSlash[0]
+
+				// find IP and Port of that Mon
+				monIP := cephutil.GetIPFromEndpoint(endpoint)
+				monPort := cephutil.GetPortFromEndpoint(endpoint)
+				logger.Infof("new external mon %q found: %s, adding it", mon.Name, endpoint)
+				c.ClusterInfo.Monitors[mon.Name] = cephclient.NewMonInfo(mon.Name, monIP, monPort)
 			} else {
 				logger.Debugf("mon %q is not in quorum and not in ClusterInfo", mon.Name)
 			}
@@ -945,7 +857,7 @@ func (c *Cluster) addOrRemoveExternalMonitor(status cephclient.MonStatusResponse
 			} else {
 				// this mon was in clusterInfo and is still in the quorum
 				// add it again
-				c.ClusterInfo.InternalMonitors[mon.Name] = oldClusterInfoMonitors[mon.Name]
+				c.ClusterInfo.Monitors[mon.Name] = oldClusterInfoMonitors[mon.Name]
 				logger.Debugf("everything is fine mon %q in the clusterInfo and its quorum status is %v", mon.Name, inQuorum)
 			}
 		}
@@ -953,33 +865,20 @@ func (c *Cluster) addOrRemoveExternalMonitor(status cephclient.MonStatusResponse
 	// compare old clusterInfo with new ClusterInfo
 	// if length differ -> the are different
 	// then check if all elements are the same
-	if len(oldClusterInfoMonitors) != len(c.ClusterInfo.InternalMonitors) {
+	if len(oldClusterInfoMonitors) != len(c.ClusterInfo.Monitors) {
 		changed = true
 	} else {
-		for _, mon := range c.ClusterInfo.InternalMonitors {
+		for _, mon := range c.ClusterInfo.Monitors {
 			if old, ok := oldClusterInfoMonitors[mon.Name]; !ok || *old != *mon {
 				changed = true
 			}
 		}
 	}
 
-	logger.Debugf("ClusterInfo.Monitors is %+v", c.ClusterInfo.InternalMonitors)
+	logger.Debugf("ClusterInfo.Monitors is %+v", c.ClusterInfo.Monitors)
 	return changed, nil
 }
 
-func monStatusToInfo(mon cephclient.MonMapEntry) *cephclient.MonInfo {
-	// let's add it to ClusterInfo
-	// FYI mon.PublicAddr is "10.97.171.131:6789/0"
-	// so we need to remove '/0'
-	endpointSlash := strings.Split(mon.PublicAddr, "/")
-	endpoint := endpointSlash[0]
-
-	// find IP and Port of that Mon
-	monIP := cephutil.GetIPFromEndpoint(endpoint)
-	monPort := cephutil.GetPortFromEndpoint(endpoint)
-	return cephclient.NewMonInfo(mon.Name, monIP, monPort)
-}
-
 func (c *Cluster) evictMonIfMultipleOnSameNode() error {
 	if c.spec.Mon.AllowMultiplePerNode {
 		logger.Debug("skipping check for multiple mons on same node since multiple mons are allowed")
diff --git a/pkg/operator/ceph/cluster/mon/mon.go b/pkg/operator/ceph/cluster/mon/mon.go
index 4d059b39c..df8fc7ff3 100644
--- a/pkg/operator/ceph/cluster/mon/mon.go
+++ b/pkg/operator/ceph/cluster/mon/mon.go
@@ -58,8 +58,6 @@ const (
 	EndpointConfigMapName = "rook-ceph-mon-endpoints"
 	// EndpointDataKey is the name of the key inside the mon configmap to get the endpoints
 	EndpointDataKey = "data"
-	// EndpointExternalMonsKey key in EndpointConfigMapName configmap containing IDs of external mons
-	EndpointExternalMonsKey = "externalMons"
 	// AppName is the name of the secret storing cluster mon.admin key, fsid and name
 	AppName = "rook-ceph-mon"
 	//nolint:gosec // OperatorCreds is the name of the secret
@@ -305,7 +303,7 @@ func (c *Cluster) startMons(targetCount int) error {
 		}
 	}
 
-	logger.Debugf("mon endpoints used are: %s", flattenMonEndpoints(c.ClusterInfo.AllMonitors()))
+	logger.Debugf("mon endpoints used are: %s", flattenMonEndpoints(c.ClusterInfo.Monitors))
 
 	// reconcile mon PDB
 	if err := c.reconcileMonPDB(); err != nil {
@@ -486,7 +484,7 @@ func (c *Cluster) ensureMonsRunning(mons []*monConfig, i, targetCount int, requi
 	// Calculate how many mons we expected to exist after this method is completed.
 	// If we are adding a new mon, we expect one more than currently exist.
 	// If we haven't created all the desired mons already, we will be adding a new one with this iteration
-	expectedMonCount := len(c.ClusterInfo.InternalMonitors)
+	expectedMonCount := len(c.ClusterInfo.Monitors)
 	if expectedMonCount < targetCount {
 		expectedMonCount++
 	}
@@ -550,12 +548,13 @@ func (c *Cluster) initClusterInfo(cephVersion cephver.CephVersion, clusterName s
 }
 
 func (c *Cluster) initMonConfig(size int) (int, []*monConfig, error) {
+
 	// initialize the mon pod info for mons that have been previously created
 	mons := c.clusterInfoToMonConfig()
 
 	// initialize mon info if we don't have enough mons (at first startup)
-	existingCount := len(c.ClusterInfo.InternalMonitors)
-	for i := len(c.ClusterInfo.InternalMonitors); i < size; i++ {
+	existingCount := len(c.ClusterInfo.Monitors)
+	for i := len(c.ClusterInfo.Monitors); i < size; i++ {
 		c.maxMonID++
 		zone, err := c.findAvailableZone(mons)
 		if err != nil {
@@ -573,7 +572,7 @@ func (c *Cluster) clusterInfoToMonConfig() []*monConfig {
 
 func (c *Cluster) clusterInfoToMonConfigWithExclude(excludedMon string) []*monConfig {
 	mons := []*monConfig{}
-	for _, monitor := range c.ClusterInfo.InternalMonitors {
+	for _, monitor := range c.ClusterInfo.Monitors {
 		if monitor.Name == excludedMon {
 			// Skip a mon if it is being failed over
 			continue
@@ -852,7 +851,7 @@ func (c *Cluster) initMonIPs(mons []*monConfig) error {
 				}
 			}
 		}
-		c.ClusterInfo.InternalMonitors[m.DaemonName] = cephclient.NewMonInfo(m.DaemonName, m.PublicIP, m.Port)
+		c.ClusterInfo.Monitors[m.DaemonName] = cephclient.NewMonInfo(m.DaemonName, m.PublicIP, m.Port)
 	}
 
 	return nil
@@ -1161,7 +1160,7 @@ func (c *Cluster) saveMonConfig() error {
 		return errors.Wrap(err, "failed to write connection config for new mons")
 	}
 
-	monEndpoints := csi.MonEndpoints(c.ClusterInfo.AllMonitors(), c.spec.RequireMsgr2())
+	monEndpoints := csi.MonEndpoints(c.ClusterInfo.Monitors, c.spec.RequireMsgr2())
 	csiConfigEntry := &csi.CSIClusterConfigEntry{
 		Namespace: c.ClusterInfo.Namespace,
 		ClusterInfo: cephcsi.ClusterInfo{
@@ -1174,7 +1173,7 @@ func (c *Cluster) saveMonConfig() error {
 		return errors.Wrap(err, "failed to update csi cluster config")
 	}
 
-	if csi.EnableCSIOperator() && len(c.ClusterInfo.AllMonitors()) > 0 {
+	if csi.EnableCSIOperator() && len(c.ClusterInfo.Monitors) > 0 {
 		err := csi.CreateUpdateCephConnection(c.context.Client, c.ClusterInfo, c.spec)
 		if err != nil {
 			return errors.Wrap(err, "failed to create/update cephConnection")
@@ -1208,7 +1207,7 @@ func (c *Cluster) persistExpectedMonDaemons() error {
 	}
 
 	csiConfigValue, err := csi.FormatCsiClusterConfig(
-		c.Namespace, c.ClusterInfo.AllMonitors())
+		c.Namespace, c.ClusterInfo.Monitors)
 	if err != nil {
 		return errors.Wrap(err, "failed to format csi config")
 	}
@@ -1220,21 +1219,14 @@ func (c *Cluster) persistExpectedMonDaemons() error {
 
 	// preserve the mons detected out of quorum
 	var monsOutOfQuorum []string
-	for monName, mon := range c.ClusterInfo.InternalMonitors {
+	for monName, mon := range c.ClusterInfo.Monitors {
 		if mon.OutOfQuorum {
 			monsOutOfQuorum = append(monsOutOfQuorum, monName)
 		}
 	}
-	extMonIDs := make([]string, 0, len(c.ClusterInfo.ExternalMons))
-	if c.ClusterInfo.ExternalMons != nil {
-		for monID := range c.ClusterInfo.ExternalMons {
-			extMonIDs = append(extMonIDs, monID)
-		}
-	}
 
 	configMap.Data = map[string]string{
-		EndpointDataKey:         flattenMonEndpoints(c.ClusterInfo.AllMonitors()),
-		EndpointExternalMonsKey: strings.Join(extMonIDs, ","),
+		EndpointDataKey: flattenMonEndpoints(c.ClusterInfo.Monitors),
 		// persist the maxMonID that was previously stored in the configmap. We are likely saving info
 		// about scheduling of the mons, but we only want to update the maxMonID once a new mon has
 		// actually been started. If the operator is restarted or the reconcile is otherwise restarted,
diff --git a/pkg/operator/ceph/cluster/mon/util.go b/pkg/operator/ceph/cluster/mon/util.go
index 39b20e582..f688a3794 100644
--- a/pkg/operator/ceph/cluster/mon/util.go
+++ b/pkg/operator/ceph/cluster/mon/util.go
@@ -17,7 +17,6 @@ limitations under the License.
 package mon
 
 import (
-	"slices"
 	"strings"
 
 	"github.com/rook/rook/pkg/daemon/ceph/client"
@@ -35,17 +34,6 @@ func monInQuorum(monitor client.MonMapEntry, quorum []int) bool {
 	return false
 }
 
-func getMonByID(monID string, monMap client.MonStatusResponse) (info client.MonMapEntry, inQuorum bool) {
-	for _, mon := range monMap.MonMap.Mons {
-		if mon.Name != monID {
-			continue
-		}
-		monRank := mon.Rank
-		return mon, slices.Contains(monMap.Quorum, monRank)
-	}
-	return client.MonMapEntry{}, false
-}
-
 // convert the mon name to the numeric mon ID
 func fullNameToIndex(name string) (int, error) {
 	// remove the "rook-ceph-mon" prefix
diff --git a/pkg/operator/ceph/cluster/nodedaemon/exporter.go b/pkg/operator/ceph/cluster/nodedaemon/exporter.go
index 8fb73b621..cbd0495e5 100644
--- a/pkg/operator/ceph/cluster/nodedaemon/exporter.go
+++ b/pkg/operator/ceph/cluster/nodedaemon/exporter.go
@@ -198,11 +198,6 @@ func getCephExporterDaemonContainer(cephCluster cephv1.CephCluster, cephVersion
 		args = append(args, "--addrs", "::")
 	}
 
-	containerPort := corev1.ContainerPort{
-		ContainerPort: int32(DefaultMetricsPort),
-		Protocol:      corev1.ProtocolTCP,
-	}
-
 	container := corev1.Container{
 		Name:            "ceph-exporter",
 		Command:         []string{"ceph-exporter"},
@@ -210,7 +205,6 @@ func getCephExporterDaemonContainer(cephCluster cephv1.CephCluster, cephVersion
 		Image:           cephImage,
 		ImagePullPolicy: controller.GetContainerImagePullPolicy(cephCluster.Spec.CephVersion.ImagePullPolicy),
 		Env:             envVars,
-		Ports:           []corev1.ContainerPort{containerPort},
 		VolumeMounts:    volumeMounts,
 		Resources:       cephv1.GetCephExporterResources(cephCluster.Spec.Resources),
 		SecurityContext: controller.PodSecurityContext(),
diff --git a/pkg/operator/ceph/controller/cluster_info.go b/pkg/operator/ceph/controller/cluster_info.go
index 7a4d3851d..2da3191ca 100644
--- a/pkg/operator/ceph/controller/cluster_info.go
+++ b/pkg/operator/ceph/controller/cluster_info.go
@@ -23,7 +23,6 @@ import (
 	"os"
 	"path"
 	"path/filepath"
-	"slices"
 	"strconv"
 	"strings"
 	"time"
@@ -57,8 +56,6 @@ const (
 	EndpointConfigMapName = "rook-ceph-mon-endpoints"
 	// EndpointDataKey is the name of the key inside the mon configmap to get the endpoints
 	EndpointDataKey = "data"
-	// EndpointExternalMonsKey key in EndpointConfigMapName configmap containing IDs of external mons
-	EndpointExternalMonsKey = "externalMons"
 	// OutOfQuorumKey is the name of the key for tracking mons detected out of quorum
 	OutOfQuorumKey = "outOfQuorum"
 	// MaxMonIDKey is the name of the max mon id used
@@ -151,7 +148,7 @@ func CreateOrLoadClusterInfo(clusterdContext *clusterd.Context, context context.
 	}
 
 	// get the existing monitor config
-	clusterInfo.ExternalMons, clusterInfo.InternalMonitors, maxMonID, monMapping, err = loadMonConfig(clusterdContext.Clientset, namespace)
+	clusterInfo.Monitors, maxMonID, monMapping, err = loadMonConfig(clusterdContext.Clientset, namespace)
 	if err != nil {
 		return nil, maxMonID, monMapping, errors.Wrap(err, "failed to get mon config")
 	}
@@ -279,34 +276,33 @@ func UpdateMonsOutOfQuorum(clientset kubernetes.Interface, namespace string, mon
 }
 
 // loadMonConfig returns the monitor endpoints and maxMonID
-func loadMonConfig(clientset kubernetes.Interface, namespace string) (extMons map[string]*cephclient.MonInfo, internalMons map[string]*cephclient.MonInfo, maxMonID int, monMapping *Mapping, err error) {
+func loadMonConfig(clientset kubernetes.Interface, namespace string) (map[string]*cephclient.MonInfo, int, *Mapping, error) {
 	ctx := context.TODO()
-	extMons = map[string]*cephclient.MonInfo{}
-	internalMons = map[string]*cephclient.MonInfo{}
-	maxMonID = -1
-	monMapping = &Mapping{
+	monEndpointMap := map[string]*cephclient.MonInfo{}
+	maxMonID := -1
+	monMapping := &Mapping{
 		Schedule: map[string]*MonScheduleInfo{},
 	}
 
 	cm, err := clientset.CoreV1().ConfigMaps(namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
 	if err != nil {
 		if !kerrors.IsNotFound(err) {
-			return nil, nil, maxMonID, monMapping, err
+			return nil, maxMonID, monMapping, err
 		}
 		// If the config map was not found, initialize the empty set of monitors
-		return extMons, internalMons, maxMonID, monMapping, nil
+		return monEndpointMap, maxMonID, monMapping, nil
 	}
 
 	// Parse the monitor List
 	if info, ok := cm.Data[EndpointDataKey]; ok {
-		internalMons = ParseMonEndpoints(info)
+		monEndpointMap = ParseMonEndpoints(info)
 	}
 
 	// Parse the mons that were detected out of quorum
 	if outOfQuorum, ok := cm.Data[OutOfQuorumKey]; ok && len(outOfQuorum) > 0 {
 		monNames := strings.Split(outOfQuorum, ",")
 		for _, monName := range monNames {
-			if monInfo, ok := internalMons[monName]; ok {
+			if monInfo, ok := monEndpointMap[monName]; ok {
 				monInfo.OutOfQuorum = true
 			} else {
 				logger.Warningf("did not find mon %q to set it out of quorum in the cluster info", monName)
@@ -326,7 +322,7 @@ func loadMonConfig(clientset kubernetes.Interface, namespace string) (extMons ma
 	}
 
 	// Make sure the max id is consistent with the current monitors
-	for _, m := range internalMons {
+	for _, m := range monEndpointMap {
 		id, _ := fullNameToIndex(m.Name)
 		if maxMonID < id {
 			maxMonID = id
@@ -340,19 +336,9 @@ func loadMonConfig(clientset kubernetes.Interface, namespace string) (extMons ma
 	if err != nil {
 		logger.Errorf("invalid JSON in mon mapping. %v", err)
 	}
-	// filter external mons:
-	if extMonIDsStr, ok := cm.Data[EndpointExternalMonsKey]; ok && extMonIDsStr != "" {
-		extMonIDs := strings.Split(extMonIDsStr, ",")
-		for monID, mon := range internalMons {
-			if slices.Contains(extMonIDs, monID) {
-				extMons[monID] = mon
-				delete(internalMons, monID)
-			}
-		}
-	}
 
-	logger.Debugf("loaded: maxMonID=%d, extMons=%+v, mons=%+v, assignment=%+v", maxMonID, extMons, internalMons, monMapping)
-	return extMons, internalMons, maxMonID, monMapping, nil
+	logger.Debugf("loaded: maxMonID=%d, mons=%+v, assignment=%+v", maxMonID, monEndpointMap, monMapping)
+	return monEndpointMap, maxMonID, monMapping, nil
 }
 
 // convert the mon name to the numeric mon ID
@@ -427,7 +413,7 @@ func PopulateExternalClusterInfo(cephClusterSpec *cephv1.ClusterSpec, context *c
 			time.Sleep(externalConnectionRetry)
 			continue
 		}
-		logger.Infof("found the cluster info to connect to the external cluster. will use %q to check health and monitor status. mons=%+v", clusterInfo.CephCred.Username, clusterInfo.AllMonitors())
+		logger.Infof("found the cluster info to connect to the external cluster. will use %q to check health and monitor status. mons=%+v", clusterInfo.CephCred.Username, clusterInfo.Monitors)
 		clusterInfo.OwnerInfo = ownerInfo
 
 		return clusterInfo, nil
diff --git a/pkg/operator/ceph/controller/predicate.go b/pkg/operator/ceph/controller/predicate.go
index 55acff4e4..631c68120 100644
--- a/pkg/operator/ceph/controller/predicate.go
+++ b/pkg/operator/ceph/controller/predicate.go
@@ -440,7 +440,7 @@ func WatchControllerPredicate() predicate.Funcs {
 			case *cephv1.CephCOSIDriver:
 				objNew := e.ObjectNew.(*cephv1.CephCOSIDriver)
 				namespacedName := fmt.Sprintf("%s/%s", objNew.Namespace, objNew.Name)
-				logger.Debugf("update event on CephCOSIDriver %q CR", namespacedName)
+				logger.Debug("update event on CephCOSIDriver %q CR", namespacedName)
 				// If the labels "do_not_reconcile" is set on the object, let's not reconcile that request
 				IsDoNotReconcile := IsDoNotReconcile(objNew.GetLabels())
 				if IsDoNotReconcile {
diff --git a/pkg/operator/ceph/csi/ceph_connection.go b/pkg/operator/ceph/csi/ceph_connection.go
index 61d89c57b..518b09d2f 100644
--- a/pkg/operator/ceph/csi/ceph_connection.go
+++ b/pkg/operator/ceph/csi/ceph_connection.go
@@ -91,7 +91,7 @@ func generateCephConnSpec(c client.Client, clusterInfo *cephclient.ClusterInfo,
 		csiClusterConnSpec.RbdMirrorDaemonCount = cephRBDMirrorList.Items[0].Spec.Count
 	}
 
-	for _, mon := range clusterInfo.AllMonitors() {
+	for _, mon := range clusterInfo.Monitors {
 		csiClusterConnSpec.Monitors = append(csiClusterConnSpec.Monitors, mon.Endpoint)
 	}
 
diff --git a/pkg/operator/ceph/csi/config.go b/pkg/operator/ceph/csi/config.go
index 13f6e760a..66168602d 100644
--- a/pkg/operator/ceph/csi/config.go
+++ b/pkg/operator/ceph/csi/config.go
@@ -35,7 +35,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-func CreateUpdateClientProfileRadosNamespace(ctx context.Context, c client.Client, clusterInfo *cephclient.ClusterInfo, cephBlockPoolRadosNamespaceName, clusterID, clusterName string) error {
+func CreateUpdateClientProfileRadosNamespace(ctx context.Context, c client.Client, clusterInfo *cephclient.ClusterInfo, cephBlockPoolRadosNamespacedName types.NamespacedName, clusterID, clusterName string) error {
 
 	logger.Info("creating ceph-csi clientProfile CR for rados namespace")
 
@@ -47,7 +47,7 @@ func CreateUpdateClientProfileRadosNamespace(ctx context.Context, c client.Clien
 			Name: clusterName,
 		},
 		Rbd: &csiopv1a1.RbdConfigSpec{
-			RadosNamespace: cephBlockPoolRadosNamespaceName,
+			RadosNamespace: cephBlockPoolRadosNamespacedName.Name,
 		},
 	}
 
@@ -73,11 +73,11 @@ func CreateUpdateClientProfileRadosNamespace(ctx context.Context, c client.Clien
 	return nil
 }
 
-func CreateUpdateClientProfileSubVolumeGroup(ctx context.Context, c client.Client, clusterInfo *cephclient.ClusterInfo, cephFilesystemSubVolumeGroupName, clusterID, clusterName string) error {
+func CreateUpdateClientProfileSubVolumeGroup(ctx context.Context, c client.Client, clusterInfo *cephclient.ClusterInfo, cephFilesystemNamespacedName types.NamespacedName, clusterID, clusterName string) error {
 
 	logger.Info("Creating ceph-csi clientProfile CR for subvolume group")
 
-	csiOpClientProfile := generateProfileSubVolumeGroupSpec(clusterInfo, cephFilesystemSubVolumeGroupName, clusterID, clusterName)
+	csiOpClientProfile := generateProfileSubVolumeGroupSpec(clusterInfo, cephFilesystemNamespacedName, clusterID, clusterName)
 
 	err := c.Get(ctx, types.NamespacedName{Name: csiOpClientProfile.Name, Namespace: csiOpClientProfile.Namespace}, csiOpClientProfile)
 	if err != nil {
@@ -101,7 +101,7 @@ func CreateUpdateClientProfileSubVolumeGroup(ctx context.Context, c client.Clien
 	return nil
 }
 
-func generateProfileSubVolumeGroupSpec(clusterInfo *cephclient.ClusterInfo, cephFilesystemSubVolumeGroupName, clusterID, clusterName string) *csiopv1a1.ClientProfile {
+func generateProfileSubVolumeGroupSpec(clusterInfo *cephclient.ClusterInfo, cephFilesystemNamespacedName types.NamespacedName, clusterID, clusterName string) *csiopv1a1.ClientProfile {
 	csiOpClientProfile := &csiopv1a1.ClientProfile{}
 	csiOpClientProfile.Name = clusterID
 	csiOpClientProfile.Namespace = os.Getenv(k8sutil.PodNamespaceEnvVar)
@@ -110,7 +110,7 @@ func generateProfileSubVolumeGroupSpec(clusterInfo *cephclient.ClusterInfo, ceph
 			Name: clusterName,
 		},
 		CephFs: &csiopv1a1.CephFsConfigSpec{
-			SubVolumeGroup: cephFilesystemSubVolumeGroupName,
+			SubVolumeGroup: cephFilesystemNamespacedName.Name,
 		},
 	}
 
diff --git a/pkg/operator/ceph/csi/spec.go b/pkg/operator/ceph/csi/spec.go
index 59e4b31ae..5b968453f 100644
--- a/pkg/operator/ceph/csi/spec.go
+++ b/pkg/operator/ceph/csi/spec.go
@@ -133,13 +133,13 @@ var (
 // manually challenging.
 var (
 	// image names
-	DefaultCSIPluginImage   = "quay.io/cephcsi/cephcsi:v3.13.1"
+	DefaultCSIPluginImage   = "quay.io/cephcsi/cephcsi:v3.13.0"
 	DefaultRegistrarImage   = "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0"
 	DefaultProvisionerImage = "registry.k8s.io/sig-storage/csi-provisioner:v5.1.0"
 	DefaultAttacherImage    = "registry.k8s.io/sig-storage/csi-attacher:v4.8.0"
 	DefaultSnapshotterImage = "registry.k8s.io/sig-storage/csi-snapshotter:v8.2.0"
 	DefaultResizerImage     = "registry.k8s.io/sig-storage/csi-resizer:v1.13.1"
-	DefaultCSIAddonsImage   = "quay.io/csiaddons/k8s-sidecar:v0.12.0"
+	DefaultCSIAddonsImage   = "quay.io/csiaddons/k8s-sidecar:v0.11.0"
 
 	// image pull policy
 	DefaultCSIImagePullPolicy = string(corev1.PullIfNotPresent)
diff --git a/pkg/operator/ceph/file/subvolumegroup/controller.go b/pkg/operator/ceph/file/subvolumegroup/controller.go
index 20e479c66..e5605785a 100644
--- a/pkg/operator/ceph/file/subvolumegroup/controller.go
+++ b/pkg/operator/ceph/file/subvolumegroup/controller.go
@@ -219,31 +219,20 @@ func (r *ReconcileCephFilesystemSubVolumeGroup) reconcile(request reconcile.Requ
 		return reconcile.Result{}, nil
 	}
 
-	cephFilesystemSubVolumeGroupName := cephFilesystemSubVolumeGroup.Name
-	if cephFilesystemSubVolumeGroup.Spec.Name != "" {
-		cephFilesystemSubVolumeGroupName = cephFilesystemSubVolumeGroup.Spec.Name
-	}
 	if cephCluster.Spec.External.Enable {
-		logger.Debug("skip creating external subvolume in external mode, create it manually, the controller will assume it's there")
+		logger.Debug("external subvolume group creation is not supported, create it manually, the controller will assume it's there")
 		err = r.updateClusterConfig(cephFilesystemSubVolumeGroup, cephCluster)
 		if err != nil {
 			return reconcile.Result{}, errors.Wrap(err, "failed to save cluster config")
 		}
 		r.updateStatus(observedGeneration, namespacedName, cephv1.ConditionReady)
-		if csi.EnableCSIOperator() {
-			err = csi.CreateUpdateClientProfileSubVolumeGroup(r.clusterInfo.Context, r.client, r.clusterInfo, cephFilesystemSubVolumeGroupName, buildClusterID(cephFilesystemSubVolumeGroup), cephCluster.Name)
-			if err != nil {
-				return reconcile.Result{}, errors.Wrap(err, "failed to create ceph csi-op config CR for subvolume")
-			}
-		}
 		return reconcile.Result{}, nil
 	}
-
 	// Build the NamespacedName to fetch the Filesystem and make sure it exists, if not we cannot
 	// create the subvolume group
+
 	cephFilesystem := &cephv1.CephFilesystem{}
 	cephFilesystemNamespacedName := types.NamespacedName{Name: cephFilesystemSubVolumeGroup.Spec.FilesystemName, Namespace: request.Namespace}
-
 	err = r.client.Get(r.opManagerContext, cephFilesystemNamespacedName, cephFilesystem)
 	if err != nil {
 		if kerrors.IsNotFound(err) {
@@ -284,9 +273,9 @@ func (r *ReconcileCephFilesystemSubVolumeGroup) reconcile(request reconcile.Requ
 	r.updateStatus(observedGeneration, request.NamespacedName, cephv1.ConditionReady)
 
 	if csi.EnableCSIOperator() {
-		err = csi.CreateUpdateClientProfileSubVolumeGroup(r.clusterInfo.Context, r.client, r.clusterInfo, cephFilesystemSubVolumeGroupName, buildClusterID(cephFilesystemSubVolumeGroup), cephCluster.Name)
+		err = csi.CreateUpdateClientProfileSubVolumeGroup(r.clusterInfo.Context, r.client, r.clusterInfo, cephFilesystemNamespacedName, buildClusterID(cephFilesystemSubVolumeGroup), cephCluster.Name)
 		if err != nil {
-			return reconcile.Result{}, errors.Wrap(err, "failed to create ceph csi-op config CR for subvolumeGroup")
+			return reconcile.Result{}, errors.Wrap(err, "failed to create ceph csi-op config CR for subVolGrp ns")
 		}
 	}
 
@@ -309,7 +298,7 @@ func (r *ReconcileCephFilesystemSubVolumeGroup) updateClusterConfig(cephFilesyst
 	csiClusterConfigEntry := csi.CSIClusterConfigEntry{
 		Namespace: r.clusterInfo.Namespace,
 		ClusterInfo: cephcsi.ClusterInfo{
-			Monitors: csi.MonEndpoints(r.clusterInfo.AllMonitors(), cephCluster.Spec.RequireMsgr2()),
+			Monitors: csi.MonEndpoints(r.clusterInfo.Monitors, cephCluster.Spec.RequireMsgr2()),
 			CephFS: cephcsi.CephFS{
 				SubvolumeGroup:     getSubvolumeGroupName(cephFilesystemSubVolumeGroup),
 				KernelMountOptions: r.clusterInfo.CSIDriverSpec.CephFS.KernelMountOptions,
diff --git a/pkg/operator/ceph/object/config.go b/pkg/operator/ceph/object/config.go
index dad9879c6..8c3608f2b 100644
--- a/pkg/operator/ceph/object/config.go
+++ b/pkg/operator/ceph/object/config.go
@@ -27,7 +27,6 @@ import (
 	cephconfig "github.com/rook/rook/pkg/operator/ceph/config"
 	"github.com/rook/rook/pkg/operator/ceph/config/keyring"
 	v1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 const (
@@ -216,38 +215,12 @@ func (c *clusterConfig) generateMonConfigOptions(rgwConfig *rgwConfig) (map[stri
 	for flag, val := range c.store.Spec.Gateway.RgwConfig {
 		if currVal, ok := configOptions[flag]; ok {
 			// RGW might break with some user-specified config overrides; log clearly to help triage
-			logger.Infof("overriding object store %q RGW config option %q with user-specified rgwConfig",
-				fmt.Sprintf("%s/%s", c.store.Namespace, c.store.Name), flag)
-			logger.Tracef("overriding object store %q RGW config option %q (current value %q) with user-specified rgwConfig %q",
+			logger.Infof("overriding object store %q RGW config option %q (current value %q) with user-specified rgwConfig %q",
 				fmt.Sprintf("%s/%s", c.store.Namespace, c.store.Name), flag, currVal, val)
 		}
 		configOptions[flag] = val
 	}
 
-	for flag, val := range c.store.Spec.Gateway.RgwConfigFromSecret {
-		if val.Key == "" || val.Name == "" {
-			return nil, fmt.Errorf("invalid object store %q rgwConfigFromSecret value %q=%+v", fmt.Sprintf("%s/%s", c.store.Namespace, c.store.Name), flag, val)
-		}
-		secret, err := c.context.Clientset.CoreV1().Secrets(c.clusterInfo.Namespace).Get(c.clusterInfo.Context, val.Name, metav1.GetOptions{})
-		if err != nil {
-			return nil, fmt.Errorf("unable to lookup secret for object store %q rgwConfigFromSecret %q=%+v", fmt.Sprintf("%s/%s", c.store.Namespace, c.store.Name), flag, val)
-		}
-		secretVal, ok := secret.Data[val.Key]
-		if !ok {
-			return nil, fmt.Errorf("unable to lookup secret for object store %q rgwConfigFromSecret %q: key %q not found in secret %q",
-				fmt.Sprintf("%s/%s", c.store.Namespace, c.store.Name), flag, val.Key, val.Name)
-		}
-
-		if currVal, ok := configOptions[flag]; ok {
-			// RGW might break with some user-specified config overrides; log clearly to help triage
-			logger.Infof("overriding object store %q RGW config option %q with user-specified rgwConfigFromSecret",
-				fmt.Sprintf("%s/%s", c.store.Namespace, c.store.Name), flag)
-			logger.Tracef("overriding object store %q RGW config option %q (current value %q) with user-specified rgwConfigFromSecret %q",
-				fmt.Sprintf("%s/%s", c.store.Namespace, c.store.Name), flag, currVal, secretVal)
-		}
-		configOptions[flag] = string(secretVal)
-	}
-
 	return configOptions, nil
 }
 
diff --git a/pkg/operator/ceph/pool/radosnamespace/controller.go b/pkg/operator/ceph/pool/radosnamespace/controller.go
index 5505cd0be..bbac0c9cc 100644
--- a/pkg/operator/ceph/pool/radosnamespace/controller.go
+++ b/pkg/operator/ceph/pool/radosnamespace/controller.go
@@ -233,24 +233,13 @@ func (r *ReconcileCephBlockPoolRadosNamespace) reconcile(request reconcile.Reque
 		return reconcile.Result{}, nil
 	}
 
-	cephBlockPoolRadosNamespaceName := cephBlockPoolRadosNamespace.Name
-	if cephBlockPoolRadosNamespace.Spec.Name != "" {
-		cephBlockPoolRadosNamespaceName = cephBlockPoolRadosNamespace.Spec.Name
-	}
-
 	if cephCluster.Spec.External.Enable {
-		logger.Debug("skip creating external radosnamespace in external mode, create it manually, the controller will assume it's there")
+		logger.Debugf("external rados namespace %q creation is not supported, create it manually, the controller will assume it's there", namespacedName)
 		err = r.updateClusterConfig(cephBlockPoolRadosNamespace, cephCluster)
 		if err != nil {
 			return reconcile.Result{}, errors.Wrap(err, "failed to save cluster config")
 		}
 		r.updateStatus(r.client, namespacedName, cephv1.ConditionReady)
-		if csi.EnableCSIOperator() {
-			err = csi.CreateUpdateClientProfileRadosNamespace(r.clusterInfo.Context, r.client, r.clusterInfo, cephBlockPoolRadosNamespaceName, buildClusterID(cephBlockPoolRadosNamespace), cephCluster.Name)
-			if err != nil {
-				return reconcile.Result{}, errors.Wrap(err, "failed to create ceph csi-op config CR for RadosNamespace")
-			}
-		}
 		return reconcile.Result{}, nil
 	}
 
@@ -271,7 +260,6 @@ func (r *ReconcileCephBlockPoolRadosNamespace) reconcile(request reconcile.Reque
 	cephBlockPool := &cephv1.CephBlockPool{}
 	pool := cephBlockPoolRadosNamespace.Spec.BlockPoolName
 	cephBlockPoolNamespacedName := types.NamespacedName{Name: pool, Namespace: request.Namespace}
-
 	err = r.client.Get(r.opManagerContext, cephBlockPoolNamespacedName, cephBlockPool)
 	if err != nil {
 		if kerrors.IsNotFound(err) {
@@ -310,7 +298,7 @@ func (r *ReconcileCephBlockPoolRadosNamespace) reconcile(request reconcile.Reque
 	r.updateStatus(r.client, namespacedName, cephv1.ConditionReady)
 
 	if csi.EnableCSIOperator() {
-		err = csi.CreateUpdateClientProfileRadosNamespace(r.clusterInfo.Context, r.client, r.clusterInfo, cephBlockPoolRadosNamespaceName, buildClusterID(cephBlockPoolRadosNamespace), cephCluster.Name)
+		err = csi.CreateUpdateClientProfileRadosNamespace(r.clusterInfo.Context, r.client, r.clusterInfo, cephBlockPoolNamespacedName, buildClusterID(cephBlockPoolRadosNamespace), cephCluster.Name)
 		if err != nil {
 			return reconcile.Result{}, errors.Wrap(err, "failed to create ceph csi-op config CR for RadosNamespace")
 		}
@@ -335,7 +323,7 @@ func (r *ReconcileCephBlockPoolRadosNamespace) updateClusterConfig(cephBlockPool
 	csiClusterConfigEntry := csi.CSIClusterConfigEntry{
 		Namespace: r.clusterInfo.Namespace,
 		ClusterInfo: cephcsi.ClusterInfo{
-			Monitors: csi.MonEndpoints(r.clusterInfo.AllMonitors(), cephCluster.Spec.RequireMsgr2()),
+			Monitors: csi.MonEndpoints(r.clusterInfo.Monitors, cephCluster.Spec.RequireMsgr2()),
 			RBD: cephcsi.RBD{
 				RadosNamespace: getRadosNamespaceName(cephBlockPoolRadosNamespace),
 			},


Test patch:
diff --git a/.github/workflows/canary-test-config/action.yaml b/.github/workflows/canary-test-config/action.yaml
index 28f08e6c6..0c815548d 100644
--- a/.github/workflows/canary-test-config/action.yaml
+++ b/.github/workflows/canary-test-config/action.yaml
@@ -7,7 +7,7 @@ runs:
     - name: setup golang
       uses: actions/setup-go@v5
       with:
-        go-version: "1.24"
+        go-version: "1.23"
 
     - name: Setup Minikube
       shell: bash --noprofile --norc -eo pipefail -x {0}
diff --git a/.github/workflows/integration-test-multi-cluster-suite.yaml b/.github/workflows/integration-test-multi-cluster-suite.yaml
index 346eaba72..f2643dfd3 100644
--- a/.github/workflows/integration-test-multi-cluster-suite.yaml
+++ b/.github/workflows/integration-test-multi-cluster-suite.yaml
@@ -65,7 +65,7 @@ jobs:
 
       - name: Artifact
         uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
-        if: always()
+        if: failure()
         with:
           name: ceph-multi-cluster-deploy-suite-artifact-${{ matrix.kubernetes-versions }}
           path: /home/runner/work/rook/rook/tests/integration/_output/tests/
diff --git a/deploy/examples/create-external-cluster-resources-tests.py b/deploy/examples/create-external-cluster-resources-tests.py
index 8c1feecf9..b3a5196c7 100644
--- a/deploy/examples/create-external-cluster-resources-tests.py
+++ b/deploy/examples/create-external-cluster-resources-tests.py
@@ -3,7 +3,7 @@ Copyright 2022 The Rook Authors. All rights reserved.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
-        http://www.apache.org/licenses/LICENSE-2.0
+	http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
diff --git a/pkg/daemon/ceph/client/config_test.go b/pkg/daemon/ceph/client/config_test.go
index cf7810312..cfb2afa20 100644
--- a/pkg/daemon/ceph/client/config_test.go
+++ b/pkg/daemon/ceph/client/config_test.go
@@ -37,7 +37,7 @@ func TestCreateDefaultCephConfig(t *testing.T) {
 		FSID:          "id",
 		MonitorSecret: "monsecret",
 		Namespace:     "foo-cluster",
-		InternalMonitors: map[string]*MonInfo{
+		Monitors: map[string]*MonInfo{
 			"node0": {Name: "mon0", Endpoint: "10.0.0.1:6789"},
 			"node1": {Name: "mon1", Endpoint: "10.0.0.2:6789"},
 		},
@@ -89,7 +89,7 @@ func TestGenerateConfigFile(t *testing.T) {
 		FSID:          "myfsid",
 		MonitorSecret: "monsecret",
 		Namespace:     ns,
-		InternalMonitors: map[string]*MonInfo{
+		Monitors: map[string]*MonInfo{
 			"node0": {Name: "mon0", Endpoint: "10.0.0.1:6789"},
 		},
 		CephCred: CephCred{Username: "admin", Secret: "mysecret"},
@@ -112,9 +112,9 @@ func TestGenerateConfigFile(t *testing.T) {
 }
 
 func verifyConfig(t *testing.T, cephConfig *CephConfig, cluster *ClusterInfo, loggingLevel int) {
-	monMembers := make([]string, len(cluster.InternalMonitors))
+	monMembers := make([]string, len(cluster.Monitors))
 	i := 0
-	for _, expectedMon := range cluster.InternalMonitors {
+	for _, expectedMon := range cluster.Monitors {
 		contained := false
 		monMembers[i] = expectedMon.Name
 		for _, actualMon := range strings.Split(cephConfig.MonMembers, " ") {
diff --git a/pkg/daemon/ceph/client/test/info.go b/pkg/daemon/ceph/client/test/info.go
index c5081e243..4aaa57ac3 100644
--- a/pkg/daemon/ceph/client/test/info.go
+++ b/pkg/daemon/ceph/client/test/info.go
@@ -51,15 +51,14 @@ func CreateTestClusterInfo(monCount int) *client.ClusterInfo {
 			Username: client.AdminUsername,
 			Secret:   "adminkey",
 		},
-		InternalMonitors: map[string]*client.MonInfo{},
-		ExternalMons:     map[string]*client.MonInfo{},
-		OwnerInfo:        ownerInfo,
-		Context:          context.TODO(),
+		Monitors:  map[string]*client.MonInfo{},
+		OwnerInfo: ownerInfo,
+		Context:   context.TODO(),
 	}
 	mons := []string{"a", "b", "c", "d", "e"}
 	for i := 0; i < monCount; i++ {
 		id := mons[i]
-		c.InternalMonitors[id] = &client.MonInfo{
+		c.Monitors[id] = &client.MonInfo{
 			Name:     id,
 			Endpoint: fmt.Sprintf("1.2.3.%d:3300", (i + 1)),
 		}
diff --git a/pkg/operator/ceph/cluster/mon/health_test.go b/pkg/operator/ceph/cluster/mon/health_test.go
index 5a9452a75..90a778dbc 100644
--- a/pkg/operator/ceph/cluster/mon/health_test.go
+++ b/pkg/operator/ceph/cluster/mon/health_test.go
@@ -29,7 +29,6 @@ import (
 	cephclient "github.com/rook/rook/pkg/daemon/ceph/client"
 	clienttest "github.com/rook/rook/pkg/daemon/ceph/client/test"
 	"github.com/rook/rook/pkg/operator/ceph/config"
-	"github.com/rook/rook/pkg/operator/ceph/controller"
 	opcontroller "github.com/rook/rook/pkg/operator/ceph/controller"
 	testopk8s "github.com/rook/rook/pkg/operator/k8sutil/test"
 	"github.com/rook/rook/pkg/operator/test"
@@ -75,7 +74,7 @@ func TestCheckHealth(t *testing.T) {
 	assert.NotNil(t, err)
 
 	c.spec.Mon.Count = 3
-	logger.Infof("initial mons: %v", c.ClusterInfo.InternalMonitors)
+	logger.Infof("initial mons: %v", c.ClusterInfo.Monitors)
 	c.waitForStart = false
 
 	c.mapping.Schedule["f"] = &opcontroller.MonScheduleInfo{
@@ -93,7 +92,7 @@ func TestCheckHealth(t *testing.T) {
 	c.ClusterInfo.Context = ctx
 	err = c.checkHealth(ctx)
 	assert.Nil(t, err)
-	logger.Infof("mons after checkHealth: %v", c.ClusterInfo.InternalMonitors)
+	logger.Infof("mons after checkHealth: %v", c.ClusterInfo.Monitors)
 	assert.ElementsMatch(t, []string{"rook-ceph-mon-a", "rook-ceph-mon-f"}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
 	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
 
@@ -106,8 +105,8 @@ func TestCheckHealth(t *testing.T) {
 		"g",
 	}
 	for _, monName := range newMons {
-		_, ok := c.ClusterInfo.InternalMonitors[monName]
-		assert.True(t, ok, fmt.Sprintf("mon %s not found in monitor list. %v", monName, c.ClusterInfo.InternalMonitors))
+		_, ok := c.ClusterInfo.Monitors[monName]
+		assert.True(t, ok, fmt.Sprintf("mon %s not found in monitor list. %v", monName, c.ClusterInfo.Monitors))
 	}
 
 	deployments, err := clientset.AppsV1().Deployments(c.Namespace).List(ctx, metav1.ListOptions{})
@@ -154,7 +153,7 @@ func TestCheckHealth(t *testing.T) {
 func TestRemoveExtraMon(t *testing.T) {
 	endpoint := "1.2.3.4:6789"
 	c := &Cluster{mapping: &opcontroller.Mapping{}}
-	c.ClusterInfo = &cephclient.ClusterInfo{InternalMonitors: map[string]*cephclient.MonInfo{
+	c.ClusterInfo = &cephclient.ClusterInfo{Monitors: map[string]*cephclient.MonInfo{
 		"a": {Name: "a", Endpoint: endpoint},
 		"b": {Name: "b", Endpoint: endpoint},
 		"c": {Name: "c", Endpoint: endpoint},
@@ -183,7 +182,7 @@ func TestRemoveExtraMon(t *testing.T) {
 		{Name: "y"},
 		{Name: "z"},
 	}}
-	c.ClusterInfo.InternalMonitors["e"] = &cephclient.MonInfo{Name: "e", Endpoint: endpoint}
+	c.ClusterInfo.Monitors["e"] = &cephclient.MonInfo{Name: "e", Endpoint: endpoint}
 	c.mapping.Schedule["a"].Zone = "x"
 	c.mapping.Schedule["b"].Zone = "y"
 	c.mapping.Schedule["c"].Zone = "y"
@@ -219,7 +218,7 @@ func TestTrackMonsOutOfQuorum(t *testing.T) {
 		context:   &clusterd.Context{Clientset: clientset, ConfigDir: tempDir},
 		ownerInfo: ownerInfo,
 		Namespace: "ns"}
-	c.ClusterInfo = &cephclient.ClusterInfo{InternalMonitors: map[string]*cephclient.MonInfo{
+	c.ClusterInfo = &cephclient.ClusterInfo{Monitors: map[string]*cephclient.MonInfo{
 		"a": {Name: "a", Endpoint: endpoint},
 		"b": {Name: "b", Endpoint: endpoint},
 		"c": {Name: "c", Endpoint: endpoint},
@@ -324,7 +323,7 @@ func TestScaleMonDeployment(t *testing.T) {
 
 	name := "a"
 	c.spec.Mon.Count = 3
-	logger.Infof("initial mons: %v", c.ClusterInfo.InternalMonitors[name])
+	logger.Infof("initial mons: %v", c.ClusterInfo.Monitors[name])
 	monConfig := &monConfig{ResourceName: resourceName(name), DaemonName: name, DataPathMap: &config.DataPathMap{}}
 	d, err := c.makeDeployment(monConfig, false)
 	require.NoError(t, err)
@@ -438,7 +437,7 @@ func TestAddRemoveMons(t *testing.T) {
 	// checking the health will increase the mons as desired all in one go
 	err := c.checkHealth(ctx)
 	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors), fmt.Sprintf("mons: %v", c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 5, len(c.ClusterInfo.Monitors), fmt.Sprintf("mons: %v", c.ClusterInfo.Monitors))
 	assert.ElementsMatch(t, []string{
 		// b is created first, no updates
 		"rook-ceph-mon-b",                    // b updated when c created
@@ -449,39 +448,39 @@ func TestAddRemoveMons(t *testing.T) {
 	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
 
 	// reducing the mon count to 3 will reduce the mon count once each time we call checkHealth
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.InternalMonitors)
+	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.Monitors)
 	c.spec.Mon.Count = 3
 	err = c.checkHealth(ctx)
 	assert.Nil(t, err)
-	assert.Equal(t, 4, len(c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 4, len(c.ClusterInfo.Monitors))
 	// No updates in unit tests w/ workaround
 	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
 	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
 
 	// after the second call we will be down to the expected count of 3
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.InternalMonitors)
+	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.Monitors)
 	err = c.checkHealth(ctx)
 	assert.Nil(t, err)
-	assert.Equal(t, 3, len(c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 3, len(c.ClusterInfo.Monitors))
 	// No updates in unit tests w/ workaround
 	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
 	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
 
 	// now attempt to reduce the mons down to quorum size 1
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.InternalMonitors)
+	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.Monitors)
 	c.spec.Mon.Count = 1
 	err = c.checkHealth(ctx)
 	assert.Nil(t, err)
-	assert.Equal(t, 2, len(c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 2, len(c.ClusterInfo.Monitors))
 	// No updates in unit tests w/ workaround
 	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
 	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
 
 	// cannot reduce from quorum size of 2 to 1
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.InternalMonitors)
+	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.Monitors)
 	err = c.checkHealth(ctx)
 	assert.Nil(t, err)
-	assert.Equal(t, 2, len(c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 2, len(c.ClusterInfo.Monitors))
 	// No updates in unit tests w/ workaround
 	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
 	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
@@ -512,7 +511,7 @@ func TestAddOrRemoveExternalMonitor(t *testing.T) {
 	changed, err = c.addOrRemoveExternalMonitor(fakeResp)
 	assert.NoError(t, err)
 	assert.False(t, changed)
-	assert.Equal(t, 1, len(c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 1, len(c.ClusterInfo.Monitors))
 
 	//
 	// TEST 2
@@ -525,7 +524,7 @@ func TestAddOrRemoveExternalMonitor(t *testing.T) {
 	assert.NoError(t, err)
 	assert.True(t, changed)
 	// ClusterInfo should shrink to 1
-	assert.Equal(t, 1, len(c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 1, len(c.ClusterInfo.Monitors))
 
 	//
 	// TEST 3
@@ -546,7 +545,7 @@ func TestAddOrRemoveExternalMonitor(t *testing.T) {
 	assert.NoError(t, err)
 	assert.True(t, changed)
 	// ClusterInfo should now have 2 monitors
-	assert.Equal(t, 2, len(c.ClusterInfo.InternalMonitors))
+	assert.Equal(t, 2, len(c.ClusterInfo.Monitors))
 }
 
 func TestNewHealthChecker(t *testing.T) {
@@ -611,522 +610,3 @@ func TestUpdateMonInterval(t *testing.T) {
 		assert.Equal(t, time.Minute, h.interval)
 	})
 }
-
-func Test_removeMonsFromQuorumStatusResponse(t *testing.T) {
-	type args struct {
-		quorumStatus cephclient.MonStatusResponse
-		idsToRemove  []string
-	}
-	tests := []struct {
-		name string
-		args args
-		want cephclient.MonStatusResponse
-	}{
-		{
-			name: "remove one mon",
-			args: args{
-				quorumStatus: cephclient.MonStatusResponse{
-					Quorum: []int{0, 1, 2},
-					MonMap: struct {
-						Mons []cephclient.MonMapEntry `json:"mons"`
-					}{
-						Mons: []cephclient.MonMapEntry{
-							{
-								Name: "a",
-								Rank: 0,
-							},
-							{
-								Name: "b",
-								Rank: 1,
-							},
-							{
-								Name: "c",
-								Rank: 2,
-							},
-						},
-					},
-				},
-				idsToRemove: []string{"b"},
-			},
-			want: cephclient.MonStatusResponse{
-				Quorum: []int{0, 2},
-				MonMap: struct {
-					Mons []cephclient.MonMapEntry `json:"mons"`
-				}{
-					Mons: []cephclient.MonMapEntry{
-						{
-							Name: "a",
-							Rank: 0,
-						},
-						{
-							Name: "c",
-							Rank: 2,
-						},
-					},
-				},
-			},
-		},
-		{
-			name: "not remove if not present",
-			args: args{
-				quorumStatus: cephclient.MonStatusResponse{
-					Quorum: []int{0, 1, 2},
-					MonMap: struct {
-						Mons []cephclient.MonMapEntry `json:"mons"`
-					}{
-						Mons: []cephclient.MonMapEntry{
-							{
-								Name: "a",
-								Rank: 0,
-							},
-							{
-								Name: "b",
-								Rank: 1,
-							},
-							{
-								Name: "c",
-								Rank: 2,
-							},
-						},
-					},
-				},
-				idsToRemove: []string{"e"},
-			},
-			want: cephclient.MonStatusResponse{
-				Quorum: []int{0, 1, 2},
-				MonMap: struct {
-					Mons []cephclient.MonMapEntry `json:"mons"`
-				}{
-					Mons: []cephclient.MonMapEntry{
-						{
-							Name: "a",
-							Rank: 0,
-						},
-						{
-							Name: "b",
-							Rank: 1,
-						},
-						{
-							Name: "c",
-							Rank: 2,
-						},
-					},
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := removeMonsFromQuorumStatusResponse(tt.args.quorumStatus, tt.args.idsToRemove); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("removeMonsFromQuorumStatusResponse() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func TestExternalMons_notInSpec_InQuorum(t *testing.T) {
-	// 1. setup test
-	ctx := context.TODO()
-	var deploymentsUpdated *[]*apps.Deployment
-	updateDeploymentAndWait, deploymentsUpdated = testopk8s.UpdateDeploymentAndWaitStub()
-
-	monQuorumResponse := clienttest.MonInQuorumResponse()
-	executor := &exectest.MockExecutor{
-		MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
-			logger.Infof("executing command: %s %+v", command, args)
-			if args[0] == "auth" && args[1] == "get-or-create-key" {
-				return "{\"key\":\"mysecurekey\"}", nil
-			}
-			return monQuorumResponse, nil
-		},
-	}
-	clientset := test.New(t, 1)
-	configDir := t.TempDir()
-	context := &clusterd.Context{
-		Clientset: clientset,
-		ConfigDir: configDir,
-		Executor:  executor,
-	}
-	ownerInfo := cephclient.NewMinimumOwnerInfoWithOwnerRef()
-	c := New(ctx, context, "ns", cephv1.ClusterSpec{}, ownerInfo)
-	setCommonMonProperties(c, 0, cephv1.MonSpec{Count: 5, AllowMultiplePerNode: true}, "myversion")
-	c.maxMonID = 0 // "a" is max mon id
-	c.waitForStart = false
-
-	// checking the health will increase the mons as desired all in one go
-	err := c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors), fmt.Sprintf("mons: %v", c.ClusterInfo.InternalMonitors))
-	assert.ElementsMatch(t, []string{
-		// b is created first, no updates
-		"rook-ceph-mon-b",                    // b updated when c created
-		"rook-ceph-mon-b", "rook-ceph-mon-c", // b and c updated when d created
-		"rook-ceph-mon-b", "rook-ceph-mon-c", "rook-ceph-mon-d", // etc.
-		"rook-ceph-mon-b", "rook-ceph-mon-c", "rook-ceph-mon-d", "rook-ceph-mon-e"},
-		testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	inital5Mons := make(map[string]*cephclient.MonInfo)
-	for k, v := range c.ClusterInfo.InternalMonitors {
-		inital5Mons[k] = v
-	}
-
-	// 2. add external mon to quorum but not in spec:
-
-	mons := make(map[string]*cephclient.MonInfo)
-	for k, v := range inital5Mons {
-		mons[k] = v
-	}
-	// add unknown mon to quorum:
-	mons["ext-mon-id"] = &cephclient.MonInfo{Name: "ext-mon-id", Endpoint: "0.0.0.0:6789"}
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(mons)
-
-	// internal mons and deployments has not changed
-	// and unknown mon was removed from quorum
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors))
-	assert.Empty(t, c.ClusterInfo.ExternalMons)
-
-	// No updates in unit tests w/ workaround
-	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err := c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Empty(t, cm.Data[EndpointExternalMonsKey])
-	monsFromCM := controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 5)
-	for id, mon := range monsFromCM {
-		assert.Equal(t, inital5Mons[id].Name, mon.Name)
-		assert.Equal(t, inital5Mons[id].Endpoint, mon.Endpoint)
-		assert.Equal(t, inital5Mons[id].OutOfQuorum, mon.OutOfQuorum)
-	}
-
-	// 3. downscale mons to 4:
-	c.spec.Mon.Count = 4
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.InternalMonitors)
-
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	// todo fix
-	assert.Equal(t, 4, len(c.ClusterInfo.InternalMonitors))
-	assert.Empty(t, c.ClusterInfo.ExternalMons)
-	// No updates in unit tests w/ workaround
-	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err = c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Empty(t, cm.Data[EndpointExternalMonsKey])
-	monsFromCM = controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 4)
-	for id, mon := range monsFromCM {
-		assert.Equal(t, inital5Mons[id].Name, mon.Name)
-		assert.Equal(t, inital5Mons[id].Endpoint, mon.Endpoint)
-		assert.Equal(t, inital5Mons[id].OutOfQuorum, mon.OutOfQuorum)
-	}
-
-	// 4. upscale back to 5:
-	c.spec.Mon.Count = 5
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.InternalMonitors)
-
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors))
-	assert.Empty(t, c.ClusterInfo.ExternalMons)
-	// No updates in unit tests w/ workaround
-	assert.Len(t, testopk8s.DeploymentNamesUpdated(deploymentsUpdated), 4)
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err = c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Empty(t, cm.Data[EndpointExternalMonsKey])
-	monsFromCM = controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 5)
-	for id, mon := range monsFromCM {
-		assert.Equal(t, c.ClusterInfo.InternalMonitors[id].Name, mon.Name)
-		assert.Equal(t, c.ClusterInfo.InternalMonitors[id].Endpoint, mon.Endpoint)
-		assert.Equal(t, c.ClusterInfo.InternalMonitors[id].OutOfQuorum, mon.OutOfQuorum)
-	}
-
-}
-
-func TestExternalMons_inSpec_notInQuorum(t *testing.T) {
-	// 1. setup test
-	ctx := context.TODO()
-	var deploymentsUpdated *[]*apps.Deployment
-	updateDeploymentAndWait, deploymentsUpdated = testopk8s.UpdateDeploymentAndWaitStub()
-
-	monQuorumResponse := clienttest.MonInQuorumResponse()
-	executor := &exectest.MockExecutor{
-		MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
-			logger.Infof("executing command: %s %+v", command, args)
-			if args[0] == "auth" && args[1] == "get-or-create-key" {
-				return "{\"key\":\"mysecurekey\"}", nil
-			}
-			return monQuorumResponse, nil
-		},
-	}
-	clientset := test.New(t, 1)
-	configDir := t.TempDir()
-	context := &clusterd.Context{
-		Clientset: clientset,
-		ConfigDir: configDir,
-		Executor:  executor,
-	}
-	ownerInfo := cephclient.NewMinimumOwnerInfoWithOwnerRef()
-	c := New(ctx, context, "ns", cephv1.ClusterSpec{}, ownerInfo)
-	setCommonMonProperties(c, 0, cephv1.MonSpec{Count: 5, AllowMultiplePerNode: true}, "myversion")
-	c.maxMonID = 0 // "a" is max mon id
-	c.waitForStart = false
-
-	// checking the health will increase the mons as desired all in one go
-	err := c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors), fmt.Sprintf("mons: %v", c.ClusterInfo.InternalMonitors))
-	assert.ElementsMatch(t, []string{
-		// b is created first, no updates
-		"rook-ceph-mon-b",                    // b updated when c created
-		"rook-ceph-mon-b", "rook-ceph-mon-c", // b and c updated when d created
-		"rook-ceph-mon-b", "rook-ceph-mon-c", "rook-ceph-mon-d", // etc.
-		"rook-ceph-mon-b", "rook-ceph-mon-c", "rook-ceph-mon-d", "rook-ceph-mon-e"},
-		testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	inital5Mons := make(map[string]*cephclient.MonInfo)
-	for k, v := range c.ClusterInfo.InternalMonitors {
-		inital5Mons[k] = v
-	}
-
-	// 2. add external mon id to spec but not to quorum
-	c.spec.Mon.ExternalMonIDs = []string{"ext-mon-id"}
-
-	// don't add ext mon to quorum:
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(inital5Mons)
-
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors))
-	assert.Empty(t, c.ClusterInfo.ExternalMons)
-
-	// No updates in unit tests w/ workaround
-	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err := c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Empty(t, cm.Data[EndpointExternalMonsKey])
-	monsFromCM := controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 5)
-	for id, mon := range monsFromCM {
-		assert.Equal(t, inital5Mons[id].Name, mon.Name)
-		assert.Equal(t, inital5Mons[id].Endpoint, mon.Endpoint)
-		assert.Equal(t, inital5Mons[id].OutOfQuorum, mon.OutOfQuorum)
-	}
-
-	// 3. downscale mons to 4:
-	c.spec.Mon.Count = 4
-
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 4, len(c.ClusterInfo.InternalMonitors))
-	assert.Empty(t, c.ClusterInfo.ExternalMons)
-	// No updates in unit tests w/ workaround
-	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err = c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Empty(t, cm.Data[EndpointExternalMonsKey])
-	monsFromCM = controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 4)
-	for id, mon := range monsFromCM {
-		assert.Equal(t, inital5Mons[id].Name, mon.Name)
-		assert.Equal(t, inital5Mons[id].Endpoint, mon.Endpoint)
-		assert.Equal(t, inital5Mons[id].OutOfQuorum, mon.OutOfQuorum)
-	}
-
-	// 4. upscale back to 5:
-	c.spec.Mon.Count = 5
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(c.ClusterInfo.InternalMonitors)
-
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors))
-	assert.Empty(t, c.ClusterInfo.ExternalMons)
-	// No updates in unit tests w/ workaround
-	assert.Len(t, testopk8s.DeploymentNamesUpdated(deploymentsUpdated), 4)
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err = c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Empty(t, cm.Data[EndpointExternalMonsKey])
-	monsFromCM = controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 5)
-	for id, mon := range monsFromCM {
-		assert.Equal(t, c.ClusterInfo.InternalMonitors[id].Name, mon.Name)
-		assert.Equal(t, c.ClusterInfo.InternalMonitors[id].Endpoint, mon.Endpoint)
-		assert.Equal(t, c.ClusterInfo.InternalMonitors[id].OutOfQuorum, mon.OutOfQuorum)
-	}
-
-}
-
-func TestExternalMons_inSpec_inQuorum(t *testing.T) {
-	// 1. setup test
-	ctx := context.TODO()
-	var deploymentsUpdated *[]*apps.Deployment
-	updateDeploymentAndWait, deploymentsUpdated = testopk8s.UpdateDeploymentAndWaitStub()
-
-	monQuorumResponse := clienttest.MonInQuorumResponse()
-	executor := &exectest.MockExecutor{
-		MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) {
-			logger.Infof("executing command: %s %+v", command, args)
-			if args[0] == "auth" && args[1] == "get-or-create-key" {
-				return "{\"key\":\"mysecurekey\"}", nil
-			}
-			return monQuorumResponse, nil
-		},
-	}
-	clientset := test.New(t, 1)
-	configDir := t.TempDir()
-	context := &clusterd.Context{
-		Clientset: clientset,
-		ConfigDir: configDir,
-		Executor:  executor,
-	}
-	ownerInfo := cephclient.NewMinimumOwnerInfoWithOwnerRef()
-	c := New(ctx, context, "ns", cephv1.ClusterSpec{}, ownerInfo)
-	setCommonMonProperties(c, 0, cephv1.MonSpec{Count: 5, AllowMultiplePerNode: true}, "myversion")
-	c.maxMonID = 0 // "a" is max mon id
-	c.waitForStart = false
-
-	// checking the health will increase the mons as desired all in one go
-	err := c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors), fmt.Sprintf("mons: %v", c.ClusterInfo.InternalMonitors))
-	assert.ElementsMatch(t, []string{
-		// b is created first, no updates
-		"rook-ceph-mon-b",                    // b updated when c created
-		"rook-ceph-mon-b", "rook-ceph-mon-c", // b and c updated when d created
-		"rook-ceph-mon-b", "rook-ceph-mon-c", "rook-ceph-mon-d", // etc.
-		"rook-ceph-mon-b", "rook-ceph-mon-c", "rook-ceph-mon-d", "rook-ceph-mon-e"},
-		testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	inital5Mons := make(map[string]*cephclient.MonInfo)
-	for k, v := range c.ClusterInfo.InternalMonitors {
-		inital5Mons[k] = v
-	}
-
-	// 2. add external mon id to spec
-	c.spec.Mon.ExternalMonIDs = []string{"ext-mon-id"}
-
-	// add ext mon to quorum:
-	mons := make(map[string]*cephclient.MonInfo)
-	for k, v := range inital5Mons {
-		mons[k] = v
-	}
-	mons["ext-mon-id"] = &cephclient.MonInfo{Name: "ext-mon-id", Endpoint: "0.0.0.0:6789"}
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(mons)
-
-	// internal mons and deployments has not changed
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors))
-	// external mon is in quorum
-	assert.Len(t, c.ClusterInfo.ExternalMons, 1)
-	assert.Equal(t, "ext-mon-id", c.ClusterInfo.ExternalMons["ext-mon-id"].Name)
-
-	// No updates in unit tests w/ workaround
-	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that ext mon is in endpoint configmap
-	cm, err := c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Equal(t, "ext-mon-id", cm.Data[EndpointExternalMonsKey])
-	monsFromCM := controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 6)
-	for id, mon := range monsFromCM {
-		if id == "ext-mon-id" {
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].Name, mon.Name)
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].Endpoint, mon.Endpoint)
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].OutOfQuorum, mon.OutOfQuorum)
-		} else {
-			assert.Equal(t, inital5Mons[id].Name, mon.Name)
-			assert.Equal(t, inital5Mons[id].Endpoint, mon.Endpoint)
-			assert.Equal(t, inital5Mons[id].OutOfQuorum, mon.OutOfQuorum)
-		}
-	}
-
-	// 3. downscale mons to 4:
-	c.spec.Mon.Count = 4
-
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 4, len(c.ClusterInfo.InternalMonitors))
-	assert.Len(t, c.ClusterInfo.ExternalMons, 1)
-	// No updates in unit tests w/ workaround
-	assert.ElementsMatch(t, []string{}, testopk8s.DeploymentNamesUpdated(deploymentsUpdated))
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err = c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Equal(t, "ext-mon-id", cm.Data[EndpointExternalMonsKey])
-	monsFromCM = controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 5)
-	for id, mon := range monsFromCM {
-		if id == "ext-mon-id" {
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].Name, mon.Name)
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].Endpoint, mon.Endpoint)
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].OutOfQuorum, mon.OutOfQuorum)
-		} else {
-			assert.Equal(t, inital5Mons[id].Name, mon.Name)
-			assert.Equal(t, inital5Mons[id].Endpoint, mon.Endpoint)
-			assert.Equal(t, inital5Mons[id].OutOfQuorum, mon.OutOfQuorum)
-		}
-	}
-
-	// 4. upscale back to 5:
-	c.spec.Mon.Count = 5
-	mons = make(map[string]*cephclient.MonInfo)
-	for k, v := range c.ClusterInfo.InternalMonitors {
-		mons[k] = v
-	}
-	mons["ext-mon-id"] = &cephclient.MonInfo{Name: "ext-mon-id", Endpoint: "0.0.0.0:6789"}
-	monQuorumResponse = clienttest.MonInQuorumResponseFromMons(mons)
-
-	err = c.checkHealth(ctx)
-	assert.Nil(t, err)
-	assert.Equal(t, 5, len(c.ClusterInfo.InternalMonitors))
-	assert.Len(t, c.ClusterInfo.ExternalMons, 1)
-	// No updates in unit tests w/ workaround
-	assert.Len(t, testopk8s.DeploymentNamesUpdated(deploymentsUpdated), 4)
-	testopk8s.ClearDeploymentsUpdated(deploymentsUpdated)
-
-	// check that unknown mon is not in endpoint configmap
-	cm, err = c.context.Clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, EndpointConfigMapName, metav1.GetOptions{})
-	assert.Nil(t, err)
-	assert.Equal(t, "ext-mon-id", cm.Data[EndpointExternalMonsKey])
-	monsFromCM = controller.ParseMonEndpoints(cm.Data[EndpointDataKey])
-	assert.Len(t, monsFromCM, 6)
-	for id, mon := range monsFromCM {
-		if id == "ext-mon-id" {
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].Name, mon.Name)
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].Endpoint, mon.Endpoint)
-			assert.Equal(t, c.ClusterInfo.ExternalMons[id].OutOfQuorum, mon.OutOfQuorum)
-		} else {
-			assert.Equal(t, c.ClusterInfo.InternalMonitors[id].Name, mon.Name)
-			assert.Equal(t, c.ClusterInfo.InternalMonitors[id].Endpoint, mon.Endpoint)
-			assert.Equal(t, c.ClusterInfo.InternalMonitors[id].OutOfQuorum, mon.OutOfQuorum)
-		}
-	}
-}
diff --git a/pkg/operator/ceph/cluster/mon/mon_test.go b/pkg/operator/ceph/cluster/mon/mon_test.go
index a481ec4d7..b4c5e0f5b 100644
--- a/pkg/operator/ceph/cluster/mon/mon_test.go
+++ b/pkg/operator/ceph/cluster/mon/mon_test.go
@@ -288,8 +288,8 @@ func TestPersistMons(t *testing.T) {
 	assert.Equal(t, map[string]string{"key": "value"}, cm.Annotations)
 
 	// Persist mon b, and remove mon a for simply testing the configmap is updated
-	c.ClusterInfo.InternalMonitors["b"] = &cephclient.MonInfo{Name: "b", Endpoint: "4.5.6.7:3300"}
-	delete(c.ClusterInfo.InternalMonitors, "a")
+	c.ClusterInfo.Monitors["b"] = &cephclient.MonInfo{Name: "b", Endpoint: "4.5.6.7:3300"}
+	delete(c.ClusterInfo.Monitors, "a")
 	err = c.persistExpectedMonDaemons()
 	assert.NoError(t, err)
 
@@ -317,7 +317,7 @@ func TestSaveMonEndpoints(t *testing.T) {
 	assert.Equal(t, "-1", cm.Data[opcontroller.MaxMonIDKey])
 
 	// update the config map
-	c.ClusterInfo.InternalMonitors["a"].Endpoint = "2.3.4.5:6789"
+	c.ClusterInfo.Monitors["a"].Endpoint = "2.3.4.5:6789"
 	c.maxMonID = 2
 	c.mapping.Schedule["a"] = &opcontroller.MonScheduleInfo{
 		Name:     "node0",
diff --git a/pkg/operator/ceph/config/store_test.go b/pkg/operator/ceph/config/store_test.go
index e9a2962b7..902a72e4c 100644
--- a/pkg/operator/ceph/config/store_test.go
+++ b/pkg/operator/ceph/config/store_test.go
@@ -45,25 +45,25 @@ func TestStore(t *testing.T) {
 		sec, e := clientset.CoreV1().Secrets(ns).Get(ctxt, StoreName, metav1.GetOptions{})
 		assert.NoError(t, e)
 		mh := strings.Split(sec.StringData["mon_host"], ",") // list of mon ip:port pairs in cluster
-		expectedEndpoints := len(ci.InternalMonitors)
+		expectedEndpoints := len(ci.Monitors)
 		if mon1EndpointsEnabled {
 			expectedEndpoints *= 2
 		}
-		assert.Equal(t, expectedEndpoints, len(mh), ci.InternalMonitors["a"].Endpoint) // we need to pass x2 since we split on "," above and that returns msgr1 and msgr2 addresses
-		mim := strings.Split(sec.StringData["mon_initial_members"], ",")               // list of mon ids in cluster
-		assert.Equal(t, len(ci.InternalMonitors), len(mim))
+		assert.Equal(t, expectedEndpoints, len(mh), ci.Monitors["a"].Endpoint) // we need to pass x2 since we split on "," above and that returns msgr1 and msgr2 addresses
+		mim := strings.Split(sec.StringData["mon_initial_members"], ",")       // list of mon ids in cluster
+		assert.Equal(t, len(ci.Monitors), len(mim))
 		// make sure every mon has its id/ip:port in mon_initial_members/mon_host
 		for _, id := range mim {
 			// cannot use "assert.Contains(t, mh, ci.Monitors[id].Endpoint)"
 			// it looks like the value is not found but if present, it might be confused by the brackets
 			contains := false
 			for _, c := range mh {
-				if strings.Contains(c, ci.InternalMonitors[id].Endpoint) {
+				if strings.Contains(c, ci.Monitors[id].Endpoint) {
 					contains = true
 				}
 			}
 			assert.True(t, contains)
-			assert.Contains(t, mim, ci.InternalMonitors[id].Name)
+			assert.Contains(t, mim, ci.Monitors[id].Name)
 		}
 	}
 
@@ -80,14 +80,14 @@ func TestStore(t *testing.T) {
 
 	// Now run the same test for v1 endpoints
 	mon1EndpointsEnabled = true
-	for _, mon := range i1.InternalMonitors {
+	for _, mon := range i1.Monitors {
 		mon.Endpoint = "1.2.3.4:6789"
 	}
 	err = s.CreateOrUpdate(i1)
 	assert.NoError(t, err)
 	assertConfigStore(i1)
 
-	for _, mon := range i3.InternalMonitors {
+	for _, mon := range i3.Monitors {
 		mon.Endpoint = "1.2.3.4:6789"
 	}
 	err = s.CreateOrUpdate(i3)
diff --git a/pkg/operator/ceph/csi/config_test.go b/pkg/operator/ceph/csi/config_test.go
index 61accd15c..8ac0c45c9 100644
--- a/pkg/operator/ceph/csi/config_test.go
+++ b/pkg/operator/ceph/csi/config_test.go
@@ -66,10 +66,10 @@ func TestCreateUpdateClientProfile(t *testing.T) {
 
 	// Create a fake client to mock API calls.
 	cl := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(object...).Build()
-	err := CreateUpdateClientProfileRadosNamespace(context.TODO(), cl, c, cephBlockPoolRadosNamespacedName.Name, cephBlockPoolRadosNamespacedName.Name, clusterName)
+	err := CreateUpdateClientProfileRadosNamespace(context.TODO(), cl, c, cephBlockPoolRadosNamespacedName, cephBlockPoolRadosNamespacedName.Name, clusterName)
 	assert.NoError(t, err)
 
-	err = CreateUpdateClientProfileSubVolumeGroup(context.TODO(), cl, c, cephSubVolGrpNamespacedName.Name, cephSubVolGrpNamespacedName.Name, clusterName)
+	err = CreateUpdateClientProfileSubVolumeGroup(context.TODO(), cl, c, cephSubVolGrpNamespacedName, cephSubVolGrpNamespacedName.Name, clusterName)
 	assert.NoError(t, err)
 
 	err = cl.Get(context.TODO(), cephBlockPoolRadosNamespacedName, csiOpClientProfile)
diff --git a/pkg/operator/ceph/csi/util_test.go b/pkg/operator/ceph/csi/util_test.go
index 94e71c8d5..74860696e 100644
--- a/pkg/operator/ceph/csi/util_test.go
+++ b/pkg/operator/ceph/csi/util_test.go
@@ -280,7 +280,7 @@ func Test_getImage(t *testing.T) {
 		{
 			name: "test with default image",
 			args: args{
-				defaultImage: "quay.io/cephcsi/cephcsi:v3.13.1",
+				defaultImage: "quay.io/cephcsi/cephcsi:v3.13.0",
 			},
 			want: DefaultCSIPluginImage,
 		},
diff --git a/pkg/operator/ceph/object/config_test.go b/pkg/operator/ceph/object/config_test.go
index 21ae599c6..f146ce617 100644
--- a/pkg/operator/ceph/object/config_test.go
+++ b/pkg/operator/ceph/object/config_test.go
@@ -17,7 +17,6 @@ limitations under the License.
 package object
 
 import (
-	"context"
 	"testing"
 
 	cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
@@ -26,8 +25,6 @@ import (
 	cephver "github.com/rook/rook/pkg/operator/ceph/version"
 	"github.com/rook/rook/pkg/operator/test"
 	"github.com/stretchr/testify/assert"
-	v1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 func newConfig(t *testing.T) *clusterConfig {
@@ -185,49 +182,3 @@ func Test_clusterConfig_generateMonConfigOptions(t *testing.T) {
 		})
 	}
 }
-
-func TestRgwConfigFromSecret(t *testing.T) {
-	objContext := &Context{
-		Context: &clusterd.Context{
-			Clientset: test.New(t, 3),
-		},
-		clusterInfo: cephclient.AdminTestClusterInfo("rook-ceph"),
-	}
-
-	objectStore := simpleStore()
-	objectStore.Spec.Gateway.RgwConfigFromSecret = map[string]v1.SecretKeySelector{
-		"rgw_secret_conf_name": {
-			LocalObjectReference: v1.LocalObjectReference{
-				Name: "my-secret",
-			},
-			Key: "secKey",
-		},
-	}
-
-	c := &clusterConfig{
-		store:       objectStore,
-		context:     objContext.Context,
-		clusterInfo: objContext.clusterInfo,
-	}
-
-	rgwConfig := &rgwConfig{}
-
-	_, err := c.generateMonConfigOptions(rgwConfig)
-	assert.Error(t, err, "error if secret not exists")
-
-	s := &v1.Secret{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      "my-secret",
-			Namespace: "rook-ceph",
-		},
-		Data: map[string][]byte{
-			"secKey": []byte("secVal"),
-		},
-	}
-	_, err = objContext.Context.Clientset.CoreV1().Secrets(objContext.clusterInfo.Namespace).Create(context.TODO(), s, metav1.CreateOptions{})
-	assert.NoError(t, err, "create secret")
-
-	got, err := c.generateMonConfigOptions(rgwConfig)
-	assert.NoError(t, err)
-	assert.EqualValues(t, "secVal", got["rgw_secret_conf_name"])
-}
diff --git a/pkg/operator/ceph/pool/radosnamespace/controller_test.go b/pkg/operator/ceph/pool/radosnamespace/controller_test.go
index 97048ded7..e47cf7e87 100644
--- a/pkg/operator/ceph/pool/radosnamespace/controller_test.go
+++ b/pkg/operator/ceph/pool/radosnamespace/controller_test.go
@@ -257,9 +257,7 @@ func TestCephBlockPoolRadosNamespaceController(t *testing.T) {
 		objects := []runtime.Object{
 			cephBlockPoolRadosNamespace,
 			cephCluster,
-			cephBlockPool,
 		}
-
 		// Create a fake client to mock API calls.
 		cl = fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(objects...).Build()
 		c.Client = cl
diff --git a/tests/framework/installer/ceph_installer.go b/tests/framework/installer/ceph_installer.go
index e7fed2c15..f59497166 100644
--- a/tests/framework/installer/ceph_installer.go
+++ b/tests/framework/installer/ceph_installer.go
@@ -146,6 +146,11 @@ func (h *CephInstaller) CreateCephOperator() (err error) {
 	}
 
 	logger.Infof("Rook operator started")
+
+	if err := h.InstallCSIOperator(); err != nil {
+		return err
+	}
+
 	return nil
 }
 
@@ -467,6 +472,45 @@ func (h *CephInstaller) GetNodeHostnames() ([]string, error) {
 	return names, nil
 }
 
+func (h *CephInstaller) InstallCSIOperator() error {
+	if h.settings.RookVersion == Version1_15 {
+		logger.Infof("Skipping the CSI operator installation for previous version of Rook")
+		return nil
+	}
+
+	logger.Infof("Starting the CSI operator")
+	_, err := h.k8shelper.KubectlWithStdin(h.Manifests.GetCSIOperator(), createFromStdinArgs...)
+	if err != nil {
+		return errors.Wrap(err, "failed to create csi-operator")
+	}
+	if !h.k8shelper.IsPodInExpectedStateWithLabel("control-plane=ceph-csi-op-controller-manager", h.settings.OperatorNamespace, "Running") {
+		logger.Error("csi-operator is not running")
+		h.k8shelper.GetLogsFromNamespace(h.settings.OperatorNamespace, "test-setup", utils.TestEnvName())
+		logger.Error("csi-operator is not Running, abort!")
+		return err
+	}
+	logger.Infof("CSI operator started")
+	return nil
+}
+
+func (h *CephInstaller) SetOperatorSetting(key, value string) error {
+	configmap := "rook-ceph-operator-config"
+	logger.Infof("applying configmap %q setting: %q -> %q", configmap, key, value)
+
+	ctx := context.TODO()
+	cm, err := h.k8shelper.Clientset.CoreV1().ConfigMaps(h.settings.OperatorNamespace).Get(ctx, configmap, metav1.GetOptions{})
+	if err != nil {
+		return errors.Wrapf(err, "error reading configmap %q", configmap)
+	}
+
+	cm.Data[key] = value
+	_, err = h.k8shelper.Clientset.CoreV1().ConfigMaps(h.settings.OperatorNamespace).Update(ctx, cm, metav1.UpdateOptions{})
+	if err != nil {
+		return errors.Wrapf(err, "failed to update configmap %q", configmap)
+	}
+	return nil
+}
+
 func (h *CephInstaller) installRookOperator() (bool, error) {
 	var err error
 
@@ -752,6 +796,14 @@ func (h *CephInstaller) UninstallRookFromMultipleNS(manifests ...CephManifests)
 		} else {
 			logger.Infof("done deleting all the resources in the operator manifest")
 		}
+
+		logger.Info("Removing the CSI operator")
+		_, err = h.k8shelper.KubectlWithStdin(h.Manifests.GetCSIOperator(), deleteFromStdinArgs...)
+		if err != nil {
+			logger.Errorf("failed to remove CSI operator. %v", err)
+		} else {
+			logger.Infof("done deleting the CSI operator")
+		}
 	}
 
 	logger.Info("removing the CRDs")
diff --git a/tests/framework/installer/ceph_manifests.go b/tests/framework/installer/ceph_manifests.go
index 60b1ddac7..873e4913a 100644
--- a/tests/framework/installer/ceph_manifests.go
+++ b/tests/framework/installer/ceph_manifests.go
@@ -30,6 +30,7 @@ type CephManifests interface {
 	Settings() *TestCephSettings
 	GetCRDs(k8shelper *utils.K8sHelper) string
 	GetCSINFSRBAC() string
+	GetCSIOperator() string
 	GetOperator() string
 	GetCommon() string
 	GetCommonExternal() string
@@ -99,6 +100,11 @@ func (m *CephManifestsMaster) GetOperator() string {
 	return m.settings.replaceOperatorSettings(manifest)
 }
 
+func (m *CephManifestsMaster) GetCSIOperator() string {
+	manifest := m.settings.readManifest("csi-operator.yaml")
+	return m.settings.replaceCSIOperatorSettings(m.settings.OperatorNamespace, manifest)
+}
+
 func (m *CephManifestsMaster) GetCommonExternal() string {
 	return m.settings.readManifest("common-external.yaml")
 }
diff --git a/tests/framework/installer/ceph_manifests_previous.go b/tests/framework/installer/ceph_manifests_previous.go
index 0b675c8ff..c0904a328 100644
--- a/tests/framework/installer/ceph_manifests_previous.go
+++ b/tests/framework/installer/ceph_manifests_previous.go
@@ -45,6 +45,10 @@ func (m *CephManifestsPreviousVersion) GetCSINFSRBAC() string {
 	return m.settings.readManifestFromGitHub("/csi/nfs/rbac.yaml")
 }
 
+func (m *CephManifestsPreviousVersion) GetCSIOperator() string {
+	return "not-supported"
+}
+
 // GetRookOperator returns rook Operator manifest
 func (m *CephManifestsPreviousVersion) GetOperator() string {
 	var manifest string
diff --git a/tests/framework/installer/ceph_settings.go b/tests/framework/installer/ceph_settings.go
index d207d1a33..055c3b6b7 100644
--- a/tests/framework/installer/ceph_settings.go
+++ b/tests/framework/installer/ceph_settings.go
@@ -80,6 +80,11 @@ func (s *TestCephSettings) readManifestFromGitHubWithClusterNamespace(filename,
 	return replaceNamespaces(filename, manifest, s.OperatorNamespace, clusterNamespace)
 }
 
+func (s *TestCephSettings) replaceCSIOperatorSettings(csiNamespace, manifest string) string {
+	manifest = strings.ReplaceAll(manifest, `namespace: rook-ceph`, `namespace: `+csiNamespace)
+	return manifest
+}
+
 func (s *TestCephSettings) replaceOperatorSettings(manifest string) string {
 	manifest = strings.ReplaceAll(manifest, `ROOK_LOG_LEVEL: "INFO"`, `ROOK_LOG_LEVEL: "DEBUG"`)
 	manifest = strings.ReplaceAll(manifest, `# CSI_LOG_LEVEL: "0"`, `CSI_LOG_LEVEL: "5"`)
diff --git a/tests/framework/utils/k8s_helper.go b/tests/framework/utils/k8s_helper.go
index 207dfa1c0..fa165ca61 100644
--- a/tests/framework/utils/k8s_helper.go
+++ b/tests/framework/utils/k8s_helper.go
@@ -1057,7 +1057,11 @@ func (k8sh *K8sHelper) GetPV(name string) (*v1.PersistentVolume, error) {
 // IsPodInExpectedState waits for 90s for a pod to be an expected state
 // If the pod is in expected state within 90s true is returned,  if not false
 func (k8sh *K8sHelper) IsPodInExpectedState(podNamePattern string, namespace string, state string) bool {
-	listOpts := metav1.ListOptions{LabelSelector: "app=" + podNamePattern}
+	return k8sh.IsPodInExpectedStateWithLabel("app="+podNamePattern, namespace, state)
+}
+
+func (k8sh *K8sHelper) IsPodInExpectedStateWithLabel(label, namespace, state string) bool {
+	listOpts := metav1.ListOptions{LabelSelector: label}
 	ctx := context.TODO()
 	for i := 0; i < RetryLoop; i++ {
 		podList, err := k8sh.Clientset.CoreV1().Pods(namespace).List(ctx, listOpts)
@@ -1069,7 +1073,7 @@ func (k8sh *K8sHelper) IsPodInExpectedState(podNamePattern string, namespace str
 			}
 		}
 
-		logger.Infof("waiting for pod with label app=%s in namespace %q to be in state %q...", podNamePattern, namespace, state)
+		logger.Infof("waiting for pod with label %s in namespace %q to be in state %q...", label, namespace, state)
 		time.Sleep(RetryInterval * time.Second)
 	}
 
diff --git a/tests/integration/ceph_upgrade_test.go b/tests/integration/ceph_upgrade_test.go
index 6bd9793a8..4d0067101 100644
--- a/tests/integration/ceph_upgrade_test.go
+++ b/tests/integration/ceph_upgrade_test.go
@@ -452,6 +452,9 @@ func (s *UpgradeSuite) upgradeToMaster() {
 		return
 	}
 
+	require.NoError(s.T(), s.installer.InstallCSIOperator())
+	require.NoError(s.T(), s.installer.SetOperatorSetting("ROOK_USE_CSI_OPERATOR", "false"))
+
 	require.NoError(s.T(), s.k8sh.ResourceOperation("apply", s.installer.Manifests.GetCRDs(s.k8sh)))
 
 	require.NoError(s.T(), s.k8sh.ResourceOperation("apply", s.installer.Manifests.GetCommon()))
diff --git a/tests/scripts/csiaddons.sh b/tests/scripts/csiaddons.sh
index c577b6dff..2b048b807 100755
--- a/tests/scripts/csiaddons.sh
+++ b/tests/scripts/csiaddons.sh
@@ -16,7 +16,7 @@
 
 set -xEo pipefail
 
-CSIADDONS_VERSION="v0.12.0"
+CSIADDONS_VERSION="v0.11.0"
 CSIADDONS_CRD_NAME="csiaddonsnodes.csiaddons.openshift.io"
 CSIADDONS_CONTAINER_NAME="csi-addons"
 
diff --git a/tests/scripts/pythonwebserver/server.py b/tests/scripts/pythonwebserver/server.py
index 6f0960310..eb2c841b0 100644
--- a/tests/scripts/pythonwebserver/server.py
+++ b/tests/scripts/pythonwebserver/server.py
@@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
-        http://www.apache.org/licenses/LICENSE-2.0
+	http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,