diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index a21cebadb73..074721d3f9d 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -85,7 +85,6 @@ Improvements * SOLR-13749: New cross collection join filter (XCJF) (Dan Fox, Kevin Watters, via Gus Heck) - Other Changes ---------------------- * SOLR-10288: Remove non-minified JavaScript from the webapp. (Erik Hatcher, marcussorealheis) @@ -203,6 +202,8 @@ Bug Fixes * SOLR-14109: Always log to stdout from server/scripts/cloud-scripts/zkcli.{bat|sh} (janhoy) +* SOLR-14122: SimUtils converts v2 to v1 request params incorrectly. (Li Cao, ab) + Other Changes --------------------- diff --git a/solr/core/src/java/org/apache/solr/cloud/autoscaling/sim/SimUtils.java b/solr/core/src/java/org/apache/solr/cloud/autoscaling/sim/SimUtils.java index b7d59de2b5c..a41886f73ed 100644 --- a/solr/core/src/java/org/apache/solr/cloud/autoscaling/sim/SimUtils.java +++ b/solr/core/src/java/org/apache/solr/cloud/autoscaling/sim/SimUtils.java @@ -330,32 +330,47 @@ public class SimUtils { private static final Map v2v1Mapping = new HashMap<>(); static { for (CollectionApiMapping.Meta meta : CollectionApiMapping.Meta.values()) { - if (meta.action != null) v2v1Mapping.put(meta.commandName, meta.action.toLower()); + if (meta.action != null) { + String key; + if (meta.commandName != null) { + key = meta.commandName; + } else { + key = meta.action.toLower(); + } + v2v1Mapping.put(key, meta.action.toLower()); + } else { + log.warn("V2 action " + meta + " has no equivalent V1 action"); + } } } /** * Convert a V2 {@link org.apache.solr.client.solrj.request.CollectionAdminRequest} to regular {@link org.apache.solr.common.params.SolrParams} * @param req request - * @return payload converted to V1 params + * @return request payload and parameters converted to V1 params */ public static ModifiableSolrParams v2AdminRequestToV1Params(V2Request req) { Map reqMap = new HashMap<>(); - ((V2Request)req).toMap(reqMap); + req.toMap(reqMap); String path = (String)reqMap.get("path"); - if (!path.startsWith("/c/") || path.length() < 4) { + if (!(path.startsWith("/c/") || path.startsWith("/collections/")) || path.length() < 4) { throw new UnsupportedOperationException("Unsupported V2 request path: " + reqMap); } - Map cmd = (Map)reqMap.get("command"); + Map cmd; + Object cmdObj = reqMap.get("command"); + if (cmdObj instanceof String) { + cmd = (Map)Utils.fromJSONString((String)cmdObj); + } else if (cmdObj instanceof Map) { + cmd = (Map)cmdObj; + } else { + throw new UnsupportedOperationException("Unsupported 'command': " + cmdObj + " (of type " + cmdObj.getClass() + ")"); + } if (cmd.size() != 1) { throw new UnsupportedOperationException("Unsupported multi-command V2 request: " + reqMap); } String a = cmd.keySet().iterator().next(); ModifiableSolrParams params = new ModifiableSolrParams(); - if (req.getParams() != null) { - params.add(req.getParams()); - } - params.add(CollectionAdminParams.COLLECTION, path.substring(3)); + params.set("path", "/admin/collections"); if (req.getParams() != null) { params.add(req.getParams()); } @@ -363,6 +378,24 @@ public class SimUtils { for (Map.Entry e : reqParams.entrySet()) { params.add(e.getKey(), e.getValue().toString()); } + // trim the leading / + path = path.substring(1); + String[] pathEls = path.split("/"); + if (pathEls.length < 2) { + throw new UnsupportedOperationException("Unsupported V2 request path: " + reqMap); + } + params.set(CollectionAdminParams.COLLECTION, pathEls[1]); + if (pathEls.length > 3) { + if (!pathEls[2].equals("shards")) { + throw new UnsupportedOperationException("Invalid V2 request path: expected 'shards' but was '" + pathEls[2] + "'"); + } + if (!pathEls[3].isBlank()) { + params.set("shard", pathEls[3]); + } + } + if (pathEls.length > 4 && !pathEls[4].isBlank()) { + params.set("replica", pathEls[4]); + } // re-map from v2 to v1 action a = v2v1Mapping.get(a); if (a == null) { diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml index 3f738d755b6..9b338794f77 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml @@ -83,25 +83,22 @@ that match a particular query. --> diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml index c6613e1cea1..6997eaff987 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml @@ -37,21 +37,18 @@ --> diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-caching.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-caching.xml index 80884fe46f6..f7d941c6fae 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-caching.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-caching.xml @@ -21,19 +21,19 @@ diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml index f5d2dbac99e..89dbecb00e4 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml @@ -83,25 +83,22 @@ that match a particular query. --> diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-deeppaging.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-deeppaging.xml index 683c8a6f4ad..7100d25b109 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-deeppaging.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-deeppaging.xml @@ -39,8 +39,8 @@ - - + + 50 500 diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml index b23ad51c125..fcb0140fb80 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml @@ -41,19 +41,16 @@ diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml index 61b471df47b..4123314c849 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml @@ -56,19 +56,16 @@ that match a particular query. --> diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml index 2c26e5ad66f..46158cd77cf 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml @@ -37,21 +37,18 @@ diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-minhash.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-minhash.xml index fa118f5c75c..7bced683b18 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-minhash.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-minhash.xml @@ -95,25 +95,22 @@ that match a particular query. --> diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml index af1b3359ffc..87dc399989e 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml @@ -82,25 +82,22 @@ that match a particular query. --> diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml index 0ccb94225d0..1bb3c97a225 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml @@ -35,8 +35,7 @@ 200 - diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml index 3ba27426038..889d1c24968 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml @@ -39,4 +39,4 @@ autowarmCount="100%" regenerator="solr.NoOpRegenerator"/> - \ No newline at end of file + diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml index 6cc49921414..2fc3c522392 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml @@ -140,23 +140,23 @@ - - - @@ -125,7 +122,6 @@ - @@ -417,8 +416,7 @@ maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed to occupy --> - @@ -428,14 +426,13 @@ document). Since Lucene internal document ids are transient, this cache will not be autowarmed. --> - diff --git a/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml index 5eee7489c56..10c8fa76aa4 100644 --- a/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml +++ b/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml @@ -56,19 +56,19 @@ - - - - diff --git a/solr/core/src/test-files/solr/configsets/xcjf/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/xcjf/conf/solrconfig.xml index b7a13796010..942e7f5db23 100644 --- a/solr/core/src/test-files/solr/configsets/xcjf/conf/solrconfig.xml +++ b/solr/core/src/test-files/solr/configsets/xcjf/conf/solrconfig.xml @@ -26,17 +26,17 @@ - - - diff --git a/solr/core/src/test/org/apache/solr/cloud/autoscaling/sim/TestSimUtils.java b/solr/core/src/test/org/apache/solr/cloud/autoscaling/sim/TestSimUtils.java new file mode 100644 index 00000000000..b2d4bea9d76 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/cloud/autoscaling/sim/TestSimUtils.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.cloud.autoscaling.sim; + +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.request.V2Request; +import org.apache.solr.common.params.SolrParams; +import org.junit.Test; + +/** + * + */ +public class TestSimUtils extends SolrTestCaseJ4 { + + @Test + public void testV2toV1() throws Exception { + // valid patterns + + V2Request req = new V2Request.Builder("/c/myCollection") + .withMethod(SolrRequest.METHOD.POST) + .withPayload("{'add-replica':{'shard':'shard2','node':'node1:1234','type':'TLOG'}}") + .withParams(params("foo", "bar")) + .build(); + SolrParams params = SimUtils.v2AdminRequestToV1Params(req); + assertEquals("/admin/collections", params.get("path")); + assertEquals("myCollection", params.get("collection")); + assertEquals("bar", params.get("foo")); + assertEquals("addreplica", params.get("action")); + assertEquals("shard2", params.get("shard")); + assertEquals("node1:1234", params.get("node")); + assertEquals("TLOG", params.get("type")); + + req = new V2Request.Builder("/c/myCollection/shards/shard1") + .withMethod(SolrRequest.METHOD.POST) + .withPayload("{'add-replica':{'shard':'shard2','node':'node1:1234','type':'TLOG'}}") + .build(); + params = SimUtils.v2AdminRequestToV1Params(req); + assertEquals("/admin/collections", params.get("path")); + assertEquals("myCollection", params.get("collection")); + // XXX should path parameters override the payload, or the other way around? + assertEquals("shard1", params.get("shard")); + + req = new V2Request.Builder("/c/myCollection/shards/shard1/core_node5") + .withMethod(SolrRequest.METHOD.POST) + .withPayload("{'deletereplica':{}}") + .build(); + params = SimUtils.v2AdminRequestToV1Params(req); + assertEquals("/admin/collections", params.get("path")); + assertEquals("myCollection", params.get("collection")); + // XXX should path parameters override the payload, or the other way around? + assertEquals("shard1", params.get("shard")); + assertEquals("core_node5", params.get("replica")); + + // invalid patterns + req = new V2Request.Builder("/invalid/myCollection") + .withMethod(SolrRequest.METHOD.POST) + .withPayload("{'add-replica':{'shard':'shard2','node':'node1:1234','type':'TLOG'}}") + .withParams(params("foo", "bar")) + .build(); + try { + params = SimUtils.v2AdminRequestToV1Params(req); + } catch (UnsupportedOperationException e) { + // expected + assertTrue(e.toString(), e.toString().contains("request path")); + } + + req = new V2Request.Builder("/collections/myCollection/foobar/xyz") + .withMethod(SolrRequest.METHOD.POST) + .withPayload("{'add-replica':{'shard':'shard2','node':'node1:1234','type':'TLOG'}}") + .withParams(params("foo", "bar")) + .build(); + try { + params = SimUtils.v2AdminRequestToV1Params(req); + } catch (UnsupportedOperationException e) { + // expected + assertTrue(e.toString(), e.toString().contains("expected 'shards'")); + } + } +} diff --git a/solr/server/solr/configsets/_default/conf/solrconfig.xml b/solr/server/solr/configsets/_default/conf/solrconfig.xml index b02c2b277ca..548d2c53fee 100644 --- a/solr/server/solr/configsets/_default/conf/solrconfig.xml +++ b/solr/server/solr/configsets/_default/conf/solrconfig.xml @@ -404,8 +404,7 @@ to occupy. Note that when this option is specified, the size and initialSize parameters are ignored. --> - @@ -417,8 +416,7 @@ maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed to occupy --> - @@ -428,14 +426,13 @@ document). Since Lucene internal document ids are transient, this cache will not be autowarmed. --> - diff --git a/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml b/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml index 34e2873b5de..98f75950b25 100644 --- a/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml +++ b/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml @@ -428,8 +428,7 @@ to occupy. Note that when this option is specified, the size and initialSize parameters are ignored. --> - @@ -441,8 +440,7 @@ maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed to occupy --> - @@ -452,14 +450,13 @@ document). Since Lucene internal document ids are transient, this cache will not be autowarmed. --> - @@ -489,7 +485,7 @@ https://lucene.apache.org/solr/guide/learning-to-rank.html -->