Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOLR-17119: Exception swallowing in ContainerPluginsApi causes some config validation errors to be ignored #2202

Merged
merged 3 commits into from
Jan 24, 2024

Conversation

ycallea
Copy link
Contributor

@ycallea ycallea commented Jan 17, 2024

https://issues.apache.org/jira/browse/SOLR-17119

Description

When registering or updating a ConfigurablePlugin through the /cluster/plugin API, exceptions raised within the void configure(T cfg) method are swallowed in ContainerPluginsApi.

This behavior can be troublesome as the exceptions raised in the configure(...) method are usually validation errors on the configuration to be applied, which are therefore ignored and allow for invalid plugin configuration to become effective.

Solution

A small change has been implemented in ContainerPluginsApi to properly include the exceptions raised while configuring a configurable cluster plugin in the response's payload errors.

A minor code clean-up on the modified method have also been included to this pull request.

Tests

  • A new test has been written to illustrate the priorly failing scenario and validate the changes.
  • Existing tests continue to pass.

Checklist

Please review the following and check all that apply:

  • I have reviewed the guidelines for How to Contribute and my code conforms to the standards described there to the best of my ability.
  • I have created a Jira issue and added the issue ID to my pull request title.
  • I have given Solr maintainers access to contribute to my PR branch. (optional but recommended)
  • I have developed this patch against the main branch.
  • I have run ./gradlew check.
  • I have added tests for my changes.
  • I have added documentation for the Reference Guide

@ycallea ycallea marked this pull request as ready for review January 17, 2024 14:57
@ycallea ycallea changed the title Exception swallowing in ContainerPluginsApi causes some config validation errors to be ignored SOLR-17119: Exception swallowing in ContainerPluginsApi causes some config validation errors to be ignored Jan 17, 2024
}

errs.forEach(payload::addError);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't change the outcome, but maybe it could be done in an else block? It's difficult to explain why, but I find this statement difficult to parse in my head in this current form.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose to implement it this way so we are only adding errors in the response's payload (payload.addError(...)) at a single place.

We could however also do it as such, to keep the same flow as before my change if it improves readability :

final List<String> errs = new ArrayList<>();
final ContainerPluginsRegistry.ApiInfo apiInfo =
    coreContainer.getContainerPluginsRegistry().createInfo(payload.getDataMap(), errs);

if (errs.isEmpty()) {
  try {
    apiInfo.init();
  } catch (Exception e) {
    log.error("Error instantiating plugin ", e);
    payload.addError(e.getMessage());
  }
} else {
  errs.forEach(payload::addError);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a side note, the way the createInfo(...) method (and by extension the ApiInfo constructor) is currently implemented feels a bit unintuitive to be honest, you have to pass it a reference to a list that will be populated with some error messages, should any validation error occur in here.

I wanted to keep the changes from this pull request small enough to only remediate the identified bug, but I feel it would be worth refactoring as part of another pull request.

In my opinion, we should just throw exceptions instead of relying on this errors' list (see ContainerPluginsRegistry.java#L329-L413), it would simplify the code and ease errors management when constructing ApiInfo objects.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't get it that only appending to errs had no effect (which is what you are fixing). I take back my comment then, it's fine as it is!

public static class ValidatableConfig implements ReflectMapWriter {
@JsonProperty public boolean willPassValidation;

public void validate() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be merged into ConfigurablePluginWithValidation#configure? Again, just to make the code easier to follow by avoiding one jump.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it can definitely be implemented this way :

public static class ConfigurablePluginWithValidation implements ConfigurablePlugin<ValidatableConfig> {
  @Override
  public void configure(ValidatableConfig cfg) {
    if (!cfg.willPassValidation) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "invalid config");
    }
  }
}

public static class ValidatableConfig implements ReflectMapWriter {
  @JsonProperty public boolean willPassValidation;
}

Is it what you have in mind ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Very minor comment, I just thought it would slightly improve the readability of the test. ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I updated the code accordingly in 729b14b

errs.add(e.getMessage());
return;
} finally {
closeWhileHandlingException(api);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this method (missing in the modified version) what was causing the exception to be swallowed?

Copy link
Contributor Author

@ycallea ycallea Jan 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception was swallowed here because the error message was mistakenly only added to the local errs list (line 151) but never included in the response's payload.

The removal of the call to closeWhileHandlingException(...) is a minor code clean-up.
In this context, the purpose of this method was to close the AnnotatedApi declared above (line 146), but as it is never instantiated this finally block always resulted in a no-op.

I therefore removed both this unused local variable declaration and the finally block which was dedicated to closing this resource.

@ycallea ycallea force-pushed the exception-swallowing-plugin-config branch from c9bc8db to 1a222e5 Compare January 19, 2024 09:20
@ycallea ycallea requested a review from pvcnt January 19, 2024 10:24
@dsmiley
Copy link
Contributor

dsmiley commented Jan 19, 2024

Can a CHANGES.txt entry be proposed here? I suppose this is an "Improvement", though I can sympathize why you filed the JIRA issue as a bug.

Copy link
Contributor

@bruno-roustant bruno-roustant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ycallea

@ycallea
Copy link
Contributor Author

ycallea commented Jan 23, 2024

Can a CHANGES.txt entry be proposed here? I suppose this is an "Improvement", though I can sympathize why you filed the JIRA issue as a bug.

I agree classifying it as a bug could be debatable.
I don't have much history on the initial implementation so I can't tell if this behavior was intended or not, thus I'm fine classifying it as an improvement if it makes more sense.

I added a CHANGES.txt entry proposal in ad6c595, for now it has been added as an improvement for the 9.5.0 release.
Let me know if you need me to make some changes to the proposed description, category and/or release 🙂

solr/CHANGES.txt Outdated
@@ -140,6 +140,9 @@ Improvements

* SOLR-17096: solr.xml now supports declaring clusterSingleton plugins (Paul McArthur, David Smiley)

* SOLR-17119: When registering a ConfigurablePlugin through the `/cluster/plugin` API using the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move to 9.6

solr/CHANGES.txt Outdated
@@ -140,6 +140,9 @@ Improvements

* SOLR-17096: solr.xml now supports declaring clusterSingleton plugins (Paul McArthur, David Smiley)

* SOLR-17119: When registering a ConfigurablePlugin through the `/cluster/plugin` API using the
V2Request client, config validation exceptions are now propagated to the callers (Yohann Callea)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest rewording "the V2Request client" to "SolrJ with V2Request". (people know SolrJ is a client and this word sets better context to users who have no clue what V2Request even is).

Curious; is"V2Request" actually pertinent to the bug? Would someone using plain HTTP see the problem?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would indeed also affect users querying the API in plain HTTP without SolrJ.
I agree that the proposed description seems to imply that the issue only exist when calling the API through SolrJ, I updated it to be less specific.

I also moved the change to 9.6.0 as requested in the previous comment.

Thanks again for your guidance 🙂

@ycallea ycallea force-pushed the exception-swallowing-plugin-config branch from ad6c595 to 0246076 Compare January 24, 2024 13:48
@dsmiley dsmiley merged commit f8160eb into apache:main Jan 24, 2024
1 check passed
dsmiley pushed a commit that referenced this pull request Jan 24, 2024
When registering or updating a ConfigurablePlugin through the `/cluster/plugin` API,
  config validation exceptions are now propagated to the callers.
freedev added a commit to freedev/solr that referenced this pull request Jan 26, 2024
* main: (27 commits)
  Update protected-branches to include branch_9_5 (apache#2211)
  SOLR-16397: Tweak v2 'REQUESTSTATUS' API to be more REST-ful  (apache#2144)
  SOLR-17120: handle null value when merging partials (apache#2214)
  SOLR-17119: Fix exception swallowing in /cluster/plugins (apache#2202)
  SOLR-15960 Cut over System.getProperty() to EnvUtils for modules (apache#2193)
  Final fix for node problems (apache#2208)
  SOLR-16397: Fix warning in merge-indices docs
  Fix nodeSetup, use node distBaseUrl instead of registry (apache#2208)
  Add next minor version 9.6.0
  SOLR-17089: Upgrade Jersey to 3.1.5 (apache#2178)
  solr-ref-guide: fix typo in result-clustering.adoc (apache#2210)
  SOLR-17074: Fixed not correctly escaped quote in bin/solr script (apache#2200)
  SOLR-15960: Rename getProp as getProperty (apache#2194)
  Add npmRegistry for nodeSetup as well (apache#2208)
  Give NPM registry option for downloading node tools (apache#2208)
  SOLR-17116: Fix INSTALLSHARDDATA async reporting (apache#2188)
  SOLR-17066: Replace 'data store' term in code and docs (apache#2201)
  SOLR-17121: Fix SchemaCodecFactory to get PostingsFormat and DocValues from field. (apache#2206)
  Sync CHANGES for 9.4.1
  Add bugfix version 9.4.1
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants