From 5a9f66cd1ce8f6146f9a0681bee5ae5f859a9c0f Mon Sep 17 00:00:00 2001 From: Ramgopal Nagaboina Date: Thu, 3 Sep 2026 20:07:18 -0400 Subject: [PATCH] server: fix ClassCastException importing an ACL rule without a traffic type createACLRuleFromMap passed the enum NetworkACLItem.TrafficType.Ingress as the getOrDefault default for a String variable, so importing a rule that omits the optional traffictype threw ClassCastException and every such rule was silently rejected into the error list. Use the enum's string form so the intended Ingress default applies. --- .../cloud/network/vpc/NetworkACLServiceImpl.java | 2 +- .../network/vpc/NetworkACLServiceImplTest.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java index 94e79ec6ea75..0d6bb704ad46 100644 --- a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -1109,7 +1109,7 @@ private NetworkACLItem createACLRuleFromMap(Map ruleMap, long ac throw new InvalidParameterValueException("Protocol is required"); } String action = (String) ruleMap.getOrDefault(ApiConstants.ACTION, "deny"); - String trafficType = (String) ruleMap.getOrDefault(ApiConstants.TRAFFIC_TYPE, NetworkACLItem.TrafficType.Ingress); + String trafficType = (String) ruleMap.getOrDefault(ApiConstants.TRAFFIC_TYPE, NetworkACLItem.TrafficType.Ingress.toString()); String forDisplay = (String) ruleMap.getOrDefault(ApiConstants.FOR_DISPLAY, "true"); // Create ACL rule using the service diff --git a/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java b/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java index b24136972ad8..f7d6318a961d 100644 --- a/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java +++ b/server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java @@ -38,7 +38,10 @@ import com.cloud.utils.net.NetUtils; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; +import org.mockito.ArgumentCaptor; +import org.springframework.test.util.ReflectionTestUtils; import org.apache.cloudstack.api.command.user.network.MoveNetworkAclItemCmd; import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLItemCmd; import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLListCmd; @@ -1506,4 +1509,17 @@ public void validateAclAssociatedToVpcTestNullVpcShouldThrowInvalidParameterValu networkAclServiceImpl.validateAclAssociatedToVpc(networkMockVpcMockId, accountMock, SOME_UUID); } + + @Test + public void createACLRuleFromMapDefaultsTrafficTypeToIngress() { + Map ruleMap = new HashMap<>(); + ruleMap.put(ApiConstants.PROTOCOL, "tcp"); + Mockito.doReturn(Mockito.mock(NetworkACLItem.class)).when(networkAclServiceImpl).createNetworkACLItem(Mockito.any()); + + ReflectionTestUtils.invokeMethod(networkAclServiceImpl, "createACLRuleFromMap", ruleMap, 1L); + + ArgumentCaptor captor = ArgumentCaptor.forClass(CreateNetworkACLCmd.class); + Mockito.verify(networkAclServiceImpl).createNetworkACLItem(captor.capture()); + Assert.assertEquals(NetworkACLItem.TrafficType.Ingress, captor.getValue().getTrafficType()); + } }