janhoy opened a new pull request, #894:
URL: https://github.com/apache/solr-operator/pull/894

   🤖 AI assisted 🤖
   
   Closes #691
   
   > Stacked on #827, which this needs for Solr version detection. Review that 
first. Only the last commit belongs to this PR.
   
   **Problem.** Solr picks replica placement with a cluster-wide plugin and 
defaults to `SimplePlacementFactory`. To use anything else, including 
`AffinityPlacementFactory`, you either maintain a full custom solr.xml or POST 
to `/api/cluster/plugin` by hand after every cluster rebuild. Neither is 
declarative, and the custom solr.xml route costs you the operator-generated 
solr.xml entirely.
   
   **Solution.** A new SolrCloud section:
   
   ```yaml
   spec:
     replicaPlacementFactory:
       class: org.apache.solr.cluster.placement.plugins.AffinityPlacementFactory
       config:
         minimalFreeDiskGB: 10
         prioritizedFreeDiskGB: 200
   ```
   
   The operator applies this through `/api/cluster/plugin` once the cloud has a 
ready pod, under the reserved name `.placement-plugin`. Removing the section 
removes the plugin. Changes need no pod restart. Also exposed as the Helm value 
`solrOptions.replicaPlacementFactory`.
   
   **Why the API and not solr.xml.** The issue proposed rendering 
`<replicaPlacementFactory>` into the generated solr.xml. Two findings moved me 
off that:
   
   - Declaring any cluster plugin in solr.xml requires 
`solr.cluster.plugin.edit.enabled=false`, or `NodeConfig` throws at startup and 
no node comes up. That property then disables the `/cluster/plugin` edit API 
cluster-wide, for cluster singletons and custom plugins too. The operator would 
be imposing a cluster-wide restriction to deliver one feature.
   - `AffinityPlacementConfig` has `long`, `Integer`, `Boolean` and three 
`Map<String,String>` fields, so solr.xml would need correct type tags plus 
nested `<lst>` rendering. Over the API the config is JSON and passes through 
untouched.
   
   **Design notes.**
   
   - `config` is arbitrary JSON via `x-kubernetes-preserve-unknown-fields`, so 
any plugin's options work with no per-option plumbing. The tradeoff is no 
schema validation of keys.
   - Re-application is driven by a hash of the desired plugin in 
`status.appliedReplicaPlacementFactory`, so Solr is called only when the spec 
changes. The hash normalises the JSON first, so reformatting the config does 
not trigger a reapply. A cloud configuring no plugin never calls Solr at all.
   - Solr 9+ is required, gated with `SolrVersionAtLeast` from #827. On Solr 8 
the setting is ignored with a warning event rather than retried.
   - No security.json change needed. The endpoint requires `COLL_EDIT_PERM`, 
which the operator's k8s role already holds through `collection-admin-edit`.
   
   **Also fixes a latent panic in `CallCollectionsApiV2`.** It passed a nil 
`*bytes.Buffer` as the request body, which is a non-nil `io.Reader` wrapping a 
nil pointer, so `http.NewRequestWithContext` panicked calling `Len()` on it. No 
previous caller passed a nil body, so this GET was the first to hit it. The 
panic aborted the whole reconcile, leaving the SolrCloud stuck at zero ready 
replicas in its status. Present on main, independent of this feature, and easy 
to split out if preferred.
   
   **Testing.** Five unit tests cover plugin construction, JSON passthrough 
including nested objects and non-string types, hash stability against 
reformatting, and rejection of invalid JSON. The full unit suite passes, as do 
`check-manifests`, `check-generated`, `check-mod`, `check-format`, `vet` and 
`check-helm`.
   
   Manually verified on a kind cluster with Solr 9.11 and the e2e harness:
   
   - the config reaches Solr intact, integers and booleans included
   - changing the config updates the existing plugin, confirmed by `GET 
/api/cluster/plugin`
   - removing the section removes the plugin and clears the status hash
   - a Solr 8.11 cloud gets the `ReplicaPlacementPluginUnsupported` warning and 
no retry loop
   - five forced reconciles produce no additional calls to Solr
   
   That manual run is also what surfaced both bugs above, so the API call is 
still worth an e2e spec. I have not added one.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to