diff --git a/solr/core/src/java/org/apache/solr/handler/configsets/CloneConfigSet.java b/solr/core/src/java/org/apache/solr/handler/configsets/CloneConfigSet.java index c90a3636563..161fbb3ea12 100644 --- a/solr/core/src/java/org/apache/solr/handler/configsets/CloneConfigSet.java +++ b/solr/core/src/java/org/apache/solr/handler/configsets/CloneConfigSet.java @@ -30,6 +30,7 @@ import org.apache.solr.cloud.ConfigSetCmds; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.ConfigSetParams; +import org.apache.solr.common.util.StrUtils; import org.apache.solr.core.CoreContainer; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; @@ -56,21 +57,26 @@ public SolrJerseyResponse cloneExistingConfigSet(CloneConfigsetRequestBody reque throws Exception { final var response = instantiateJerseyResponse(SolrJerseyResponse.class); SolrIdentifierValidator.validateConfigSetName(requestBody.name); + final String baseConfigSetName = + StrUtils.isNullOrEmpty(requestBody.baseConfigSet) + ? CloneConfigsetRequestBody.DEFAULT_CONFIGSET + : requestBody.baseConfigSet; + if (configSetService.checkConfigExists(requestBody.name)) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "ConfigSet already exists: " + requestBody.name); } // is there a base config that already exists - if (!configSetService.checkConfigExists(requestBody.baseConfigSet)) { + if (!configSetService.checkConfigExists(baseConfigSetName)) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, - "Base ConfigSet does not exist: " + requestBody.baseConfigSet); + "Base ConfigSet does not exist: " + baseConfigSetName); } final Map configsetCommandMsg = new HashMap<>(); configsetCommandMsg.put(NAME, requestBody.name); - configsetCommandMsg.put(ConfigSetCmds.BASE_CONFIGSET, requestBody.baseConfigSet); + configsetCommandMsg.put(ConfigSetCmds.BASE_CONFIGSET, baseConfigSetName); if (requestBody.properties != null) { for (Map.Entry e : requestBody.properties.entrySet()) { configsetCommandMsg.put( diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java index 6736af93b68..530daf60c8d 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java @@ -200,6 +200,30 @@ public void testCreate() throws Exception { "solr"); } + @Test + public void testV2CreateWithoutBaseConfigsetUsesDefault() throws Exception { + final String configSetName = "v2ConfigSetNoBase" + System.nanoTime(); + final String baseUrl = cluster.getJettySolrRunners().get(0).getBaseUrl().toString(); + try (final SolrClient solrClient = getHttpSolrClient(baseUrl); + SolrZkClient zkClient = + new SolrZkClient.Builder() + .withUrl(cluster.getZkServer().getZkAddress()) + .withTimeout(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS) + .withConnTimeOut(AbstractZkTestCase.TIMEOUT, TimeUnit.MILLISECONDS) + .build()) { + assertFalse(getConfigSetService().checkConfigExists(configSetName)); + + final var createRequest = new ConfigsetsApi.CloneExistingConfigSet(); + createRequest.setName(configSetName); + final var response = createRequest.process(solrClient); + + assertNotNull(response); + assertEquals(0, response.responseHeader.status); + assertTrue(getConfigSetService().checkConfigExists(configSetName)); + assertTrue(zkClient.exists("/configs/" + configSetName + "/solrconfig.xml")); + } + } + private void setupBaseConfigSet(String baseConfigSetName, Map oldProps) throws Exception { final Path configDir = getFile("solr").resolve("configsets/configset-2/conf"); diff --git a/solr/core/src/test/org/apache/solr/handler/configsets/CloneConfigSetAPITest.java b/solr/core/src/test/org/apache/solr/handler/configsets/CloneConfigSetAPITest.java new file mode 100644 index 00000000000..55d7c6681ed --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/configsets/CloneConfigSetAPITest.java @@ -0,0 +1,73 @@ +/* + * 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.handler.configsets; + +import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.apache.solr.SolrTestCase; +import org.apache.solr.client.api.model.CloneConfigsetRequestBody; +import org.apache.solr.common.SolrException; +import org.apache.solr.core.ConfigSetService; +import org.apache.solr.core.CoreContainer; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** Unit tests for {@link CloneConfigSet#cloneExistingConfigSet(CloneConfigsetRequestBody)}. */ +public class CloneConfigSetAPITest extends SolrTestCase { + + private CoreContainer mockCoreContainer; + private ConfigSetService mockConfigSetService; + + @BeforeClass + public static void ensureWorkingMockito() { + assumeWorkingMockito(); + } + + @Before + public void setup() { + mockCoreContainer = mock(CoreContainer.class); + mockConfigSetService = mock(ConfigSetService.class); + when(mockCoreContainer.getConfigSetService()).thenReturn(mockConfigSetService); + } + + @Test + public void testMissingBaseConfigSetDefaultsToDefaultConfigset() throws Exception { + when(mockConfigSetService.checkConfigExists("newconfig")).thenReturn(false); + when(mockConfigSetService.checkConfigExists(CloneConfigsetRequestBody.DEFAULT_CONFIGSET)) + .thenReturn(false); + + final var requestBody = new CloneConfigsetRequestBody(); + requestBody.name = "newconfig"; + requestBody.baseConfigSet = null; + + final var api = new CloneConfigSet(mockCoreContainer, null, null); + final SolrException ex = + assertThrows(SolrException.class, () -> api.cloneExistingConfigSet(requestBody)); + + assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, ex.code()); + assertTrue( + ex.getMessage() + .contains( + "Base ConfigSet does not exist: " + CloneConfigsetRequestBody.DEFAULT_CONFIGSET)); + verify(mockConfigSetService).checkConfigExists(CloneConfigsetRequestBody.DEFAULT_CONFIGSET); + } +}