From ad122831c0f9f3fe56653317a9a163a2d6c3cb0b Mon Sep 17 00:00:00 2001 From: Ramgopal Nagaboina Date: Thu, 3 Sep 2026 19:56:56 -0400 Subject: [PATCH] config: persist config subgroups with their name and group id createOrupdateConfigObject created a missing configuration subgroup with the no-arg ConfigurationSubGroupVO constructor, so the row was written with a null name and null group_id. Because the name stayed null, the next findByNameAndGroup lookup missed again and inserted another null row on every management-server restart. Build the subgroup with its name and precedence and set its group id, matching the sibling configuration-group branch. --- .../config/impl/ConfigDepotImpl.java | 3 +- .../config/impl/ConfigDepotImplTest.java | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java index db9cb172ccd5..32bac8ac8260 100644 --- a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java +++ b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java @@ -172,7 +172,8 @@ private void createOrupdateConfigObject(Date date, String componentName, ConfigK Pair subGroup = key.subGroup(); ConfigurationSubGroupVO subGroupVO = _configSubGroupDao.findByNameAndGroup(subGroup.first(), groupId); if (subGroupVO == null) { - subGroupVO = new ConfigurationSubGroupVO(); + subGroupVO = new ConfigurationSubGroupVO(subGroup.first(), null, subGroup.second()); + subGroupVO.setGroupId(groupId); subGroupVO = _configSubGroupDao.persist(subGroupVO); } subGroupId = subGroupVO.getId(); diff --git a/framework/config/src/test/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImplTest.java b/framework/config/src/test/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImplTest.java index ca2f54f1442c..a0b9287acdca 100644 --- a/framework/config/src/test/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImplTest.java +++ b/framework/config/src/test/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImplTest.java @@ -24,24 +24,54 @@ import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; +import com.cloud.utils.Pair; + +import java.util.Date; + @RunWith(MockitoJUnitRunner.class) public class ConfigDepotImplTest { @Mock ConfigurationDao _configDao; + @Mock + ConfigurationSubGroupDao _configSubGroupDao; + @InjectMocks private ConfigDepotImpl configDepotImpl = new ConfigDepotImpl(); + @Test + public void createConfigObjectPersistsSubGroupWithNameAndGroupId() { + ConfigKey key = Mockito.mock(ConfigKey.class); + Mockito.when(key.group()).thenReturn(null); + Mockito.when(key.subGroup()).thenReturn(new Pair<>("ConsoleProxy VM", 5L)); + Mockito.when(key.key()).thenReturn("consoleproxy.capacity.standby"); + Mockito.when(key.scope()).thenReturn(ConfigKey.Scope.Global); + Mockito.when(_configSubGroupDao.findByNameAndGroup("ConsoleProxy VM", 1L)).thenReturn(null); + Mockito.when(_configSubGroupDao.persist(Mockito.any(ConfigurationSubGroupVO.class))) + .thenAnswer(invocation -> invocation.getArgument(0)); + Mockito.when(_configDao.findById("consoleproxy.capacity.standby")).thenReturn(Mockito.mock(ConfigurationVO.class)); + + ArgumentCaptor captor = ArgumentCaptor.forClass(ConfigurationSubGroupVO.class); + ReflectionTestUtils.invokeMethod(configDepotImpl, "createOrupdateConfigObject", + new Date(), "components", key, "someValue"); + + Mockito.verify(_configSubGroupDao).persist(captor.capture()); + Assert.assertEquals("ConsoleProxy VM", captor.getValue().getName()); + Assert.assertEquals(Long.valueOf(1L), captor.getValue().getGroupId()); + } + @Test public void createEmptyScopeLevelMappingsTest() { configDepotImpl.createEmptyScopeLevelMappings();