config: persist config subgroups with their name and group id - #14050
Conversation
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.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 4.20 #14050 +/- ##
=========================================
Coverage 16.34% 16.35%
- Complexity 13574 13579 +5
=========================================
Files 5669 5669
Lines 501368 501369 +1
Branches 60903 60903
=========================================
+ Hits 81964 81982 +18
+ Misses 410219 410205 -14
+ Partials 9185 9182 -3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@blueorangutan package |
|
@sureshanaparti a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19170 |
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Pull request overview
Fixes config subgroup persistence to avoid repeatedly inserting null-name/null-group rows on restart by constructing ConfigurationSubGroupVO with proper metadata and adding a unit test to lock in the behavior.
Changes:
- Create
ConfigurationSubGroupVOwith subgroup name and precedence, and explicitly setgroupIdbefore persisting. - Add a unit test that captures the persisted subgroup VO and asserts
nameandgroupId.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java | Ensures newly created subgroups are persisted with correct name/precedence and groupId. |
| framework/config/src/test/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImplTest.java | Adds a regression test verifying subgroup persistence includes name and groupId. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| 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<ConfigurationSubGroupVO> 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()); |
| 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<ConfigurationSubGroupVO> 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()); |
| ConfigurationSubGroupVO subGroupVO = _configSubGroupDao.findByNameAndGroup(subGroup.first(), groupId); | ||
| if (subGroupVO == null) { | ||
| subGroupVO = new ConfigurationSubGroupVO(); | ||
| subGroupVO = new ConfigurationSubGroupVO(subGroup.first(), null, subGroup.second()); |
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.
Tested: new unit test createConfigObjectPersistsSubGroupWithNameAndGroupId (captures the persisted VO); ConfigDepotImplTest green.