Skip to content

Commit b08f9e0

Browse files
[CLOUDSTACK-10301] Allow updating the network ACL list name and Description (#2462)
* [CLOUDSTACK-10301] Allow updating the network ACL list name and description * Fixes suggested by Daan
1 parent 5004268 commit b08f9e0

23 files changed

Lines changed: 180 additions & 27 deletions

File tree

api/src/main/java/com/cloud/network/vpc/NetworkACLService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd;
2323
import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd;
2424
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLItemCmd;
25+
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLListCmd;
2526

2627
import com.cloud.exception.ResourceUnavailableException;
2728
import com.cloud.utils.Pair;
@@ -38,7 +39,7 @@ public interface NetworkACLService {
3839
NetworkACL getNetworkACL(long id);
3940

4041
/**
41-
* List NetworkACLs by Id/Name/Network or Vpc it belongs to
42+
* List NetworkACLs by Id/Name/Network or VPC it belongs to
4243
*/
4344
Pair<List<? extends NetworkACL>, Integer> listNetworkACLs(ListNetworkACLListsCmd cmd);
4445

@@ -87,6 +88,6 @@ public interface NetworkACLService {
8788
*/
8889
boolean replaceNetworkACLonPrivateGw(long aclId, long privateGatewayId) throws ResourceUnavailableException;
8990

90-
NetworkACL updateNetworkACL(Long id, String customId, Boolean forDisplay);
91+
NetworkACL updateNetworkACL(UpdateNetworkACLListCmd updateNetworkACLListCmd);
9192

9293
}

api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLListCmd.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
import com.cloud.network.vpc.NetworkACL;
3232
import com.cloud.user.Account;
3333

34-
@APICommand(name = "updateNetworkACLList", description = "Updates network ACL list", responseObject = SuccessResponse.class, since = "4.4",
35-
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
34+
@APICommand(name = "updateNetworkACLList", description = "Updates network ACL list", responseObject = SuccessResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
3635
public class UpdateNetworkACLListCmd extends BaseAsyncCustomIdCmd {
3736
public static final Logger s_logger = Logger.getLogger(UpdateNetworkACLListCmd.class.getName());
3837
private static final String s_name = "updatenetworkacllistresponse";
@@ -44,9 +43,16 @@ public class UpdateNetworkACLListCmd extends BaseAsyncCustomIdCmd {
4443
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = NetworkACLResponse.class, required = true, description = "the ID of the network ACL")
4544
private Long id;
4645

47-
@Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the list to the end user or not", since = "4.4", authorized = {RoleType.Admin})
46+
@Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the list to the end user or not", since = "4.4", authorized = {
47+
RoleType.Admin})
4848
private Boolean display;
4949

50+
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "Name of the network ACL list")
51+
private String name;
52+
53+
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Description of the network ACL list")
54+
private String description;
55+
5056
/////////////////////////////////////////////////////
5157
/////////////////// Accessors ///////////////////////
5258
/////////////////////////////////////////////////////
@@ -85,7 +91,7 @@ public long getEntityOwnerId() {
8591

8692
@Override
8793
public void execute() throws ResourceUnavailableException {
88-
NetworkACL acl = _networkACLService.updateNetworkACL(id, this.getCustomId(), getDisplay());
94+
NetworkACL acl = _networkACLService.updateNetworkACL(this);
8995
NetworkACLResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl);
9096
setResponseObject(aclResponse);
9197
aclResponse.setResponseName(getCommandName());
@@ -97,4 +103,12 @@ public void checkUuid() {
97103
_uuidMgr.checkUuid(this.getCustomId(), NetworkACL.class);
98104
}
99105
}
106+
107+
public String getDescription() {
108+
return description;
109+
}
110+
111+
public String getName() {
112+
return name;
113+
}
100114
}

engine/schema/src/main/java/com/cloud/network/vpc/NetworkACLVO.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,12 @@ public void setVpcId(long vpcId) {
101101
public boolean isDisplay() {
102102
return display;
103103
}
104+
105+
public void setDescription(String description) {
106+
this.description = description;
107+
}
108+
109+
public void setName(String name) {
110+
this.name = name;
111+
}
104112
}

server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd;
2929
import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd;
3030
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLItemCmd;
31+
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLListCmd;
3132
import org.apache.cloudstack.context.CallContext;
3233
import org.apache.commons.collections.CollectionUtils;
3334
import org.apache.commons.lang.StringUtils;
@@ -907,20 +908,30 @@ protected NetworkACLItemVO validateNetworkAclRuleIdAndRetrieveIt(UpdateNetworkAC
907908

908909
@Override
909910
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_UPDATE, eventDescription = "updating network acl", async = true)
910-
public NetworkACL updateNetworkACL(final Long id, final String customId, final Boolean forDisplay) {
911-
final NetworkACLVO acl = _networkACLDao.findById(id);
912-
final Vpc vpc = _entityMgr.findById(Vpc.class, acl.getVpcId());
913-
final Account caller = CallContext.current().getCallingAccount();
911+
public NetworkACL updateNetworkACL(UpdateNetworkACLListCmd updateNetworkACLListCmd) {
912+
Long id = updateNetworkACLListCmd.getId();
913+
NetworkACLVO acl = _networkACLDao.findById(id);
914+
Vpc vpc = _entityMgr.findById(Vpc.class, acl.getVpcId());
915+
916+
Account caller = CallContext.current().getCallingAccount();
914917
_accountMgr.checkAccess(caller, null, true, vpc);
915918

916-
if (customId != null) {
919+
String name = updateNetworkACLListCmd.getName();
920+
if (StringUtils.isNotBlank(name)) {
921+
acl.setName(name);
922+
}
923+
String description = updateNetworkACLListCmd.getDescription();
924+
if (StringUtils.isNotBlank(description)) {
925+
acl.setDescription(description);
926+
}
927+
String customId = updateNetworkACLListCmd.getCustomId();
928+
if (StringUtils.isNotBlank(customId)) {
917929
acl.setUuid(customId);
918930
}
919-
931+
Boolean forDisplay = updateNetworkACLListCmd.getDisplay();
920932
if (forDisplay != null) {
921933
acl.setDisplay(forDisplay);
922934
}
923-
924935
_networkACLDao.update(id, acl);
925936
return _networkACLDao.findById(id);
926937
}

server/src/test/java/com/cloud/network/vpc/NetworkACLServiceImplTest.java

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.apache.cloudstack.api.ServerApiException;
2424
import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd;
2525
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLItemCmd;
26+
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLListCmd;
2627
import org.apache.cloudstack.context.CallContext;
2728
import org.junit.Assert;
2829
import org.junit.Before;
@@ -46,12 +47,14 @@
4647
import com.cloud.network.dao.NetworkVO;
4748
import com.cloud.network.vpc.NetworkACLItem.Action;
4849
import com.cloud.network.vpc.NetworkACLItem.TrafficType;
50+
import com.cloud.network.vpc.dao.NetworkACLDao;
4951
import com.cloud.user.Account;
5052
import com.cloud.user.AccountManager;
5153
import com.cloud.utils.db.EntityManager;
5254
import com.cloud.utils.exception.CloudRuntimeException;
5355

5456
@RunWith(PowerMockRunner.class)
57+
@PrepareForTest(CallContext.class)
5558
public class NetworkACLServiceImplTest {
5659

5760
@Spy
@@ -64,9 +67,11 @@ public class NetworkACLServiceImplTest {
6467
@Mock
6568
private NetworkACLItemDao networkAclItemDaoMock;
6669
@Mock
67-
private EntityManager EntityManagerMock;
70+
private EntityManager entityManagerMock;
6871
@Mock
69-
private AccountManager AccountManager;
72+
private AccountManager accountManagerMock;
73+
@Mock
74+
private NetworkACLDao networkAclDaoMock;
7075

7176
@Mock
7277
private CreateNetworkACLCmd createNetworkAclCmdMock;
@@ -78,13 +83,22 @@ public class NetworkACLServiceImplTest {
7883
private NetworkACL networkAclMock;
7984
@Mock
8085
private NetworkACLItemVO networkAclItemVoMock;
86+
@Mock
87+
private NetworkACLVO networkACLVOMock;
88+
@Mock
89+
private UpdateNetworkACLListCmd updateNetworkACLListCmdMock;
8190

8291
private Long networkAclMockId = 1L;
8392
private Long networkOfferingMockId = 2L;
8493
private Long networkMockVpcMockId = 3L;
94+
private long networkAclListId = 1l;
8595

8696
@Before
8797
public void befoteTest() {
98+
PowerMockito.mockStatic(CallContext.class);
99+
PowerMockito.when(CallContext.current()).thenReturn(Mockito.mock(CallContext.class));
100+
101+
Mockito.when(networkAclDaoMock.findById(networkAclListId)).thenReturn(networkACLVOMock);
88102
Mockito.when(createNetworkAclCmdMock.getNetworkId()).thenReturn(1L);
89103
Mockito.when(createNetworkAclCmdMock.getProtocol()).thenReturn("tcp");
90104

@@ -215,15 +229,15 @@ public void createAclListForNetworkAndReturnAclListIdTestServicesNotSupportedByN
215229
@Test(expected = InvalidParameterValueException.class)
216230
public void createAclListForNetworkAndReturnAclListIdTestServicesSupportedByNetworkOfferingButVpcNotFound() {
217231
Mockito.doReturn(true).when(networkModelMock).areServicesSupportedByNetworkOffering(networkOfferingMockId, Network.Service.NetworkACL);
218-
Mockito.doReturn(null).when(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
232+
Mockito.doReturn(null).when(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
219233

220234
networkAclServiceImpl.createAclListForNetworkAndReturnAclListId(createNetworkAclCmdMock, networkMock);
221235
}
222236

223237
@Test(expected = CloudRuntimeException.class)
224238
public void createAclListForNetworkAndReturnAclListIdTestCreateNetworkAclReturnsNull() {
225239
Mockito.doReturn(true).when(networkModelMock).areServicesSupportedByNetworkOffering(networkOfferingMockId, Network.Service.NetworkACL);
226-
Mockito.doReturn(Mockito.mock(Vpc.class)).when(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
240+
Mockito.doReturn(Mockito.mock(Vpc.class)).when(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
227241
Mockito.doReturn(null).when(networkAclManager).createNetworkACL(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyBoolean());
228242

229243
networkAclServiceImpl.createAclListForNetworkAndReturnAclListId(createNetworkAclCmdMock, networkMock);
@@ -232,7 +246,7 @@ public void createAclListForNetworkAndReturnAclListIdTestCreateNetworkAclReturns
232246
@Test(expected = CloudRuntimeException.class)
233247
public void createAclListForNetworkAndReturnAclListIdTestAclNetworkIsCreatedButNotApplied() throws ResourceUnavailableException {
234248
Mockito.doReturn(true).when(networkModelMock).areServicesSupportedByNetworkOffering(networkOfferingMockId, Network.Service.NetworkACL);
235-
Mockito.doReturn(Mockito.mock(Vpc.class)).when(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
249+
Mockito.doReturn(Mockito.mock(Vpc.class)).when(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
236250
Mockito.doReturn(Mockito.mock(NetworkACL.class)).when(networkAclManager).createNetworkACL(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyBoolean());
237251
Mockito.doReturn(false).when(networkAclManager).replaceNetworkACL(Mockito.any(NetworkACL.class), Mockito.any(NetworkVO.class));
238252

@@ -246,7 +260,7 @@ public void createAclListForNetworkAndReturnAclListIdTestAclNetworkIsCreatedButN
246260
@Test(expected = CloudRuntimeException.class)
247261
public void createAclListForNetworkAndReturnAclListIdTestAclNetworkIsCreatedButNotAppliedWithException() throws ResourceUnavailableException {
248262
Mockito.doReturn(true).when(networkModelMock).areServicesSupportedByNetworkOffering(networkOfferingMockId, Network.Service.NetworkACL);
249-
Mockito.doReturn(Mockito.mock(Vpc.class)).when(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
263+
Mockito.doReturn(Mockito.mock(Vpc.class)).when(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
250264
Mockito.doReturn(Mockito.mock(NetworkACL.class)).when(networkAclManager).createNetworkACL(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyBoolean());
251265

252266
Mockito.doThrow(ResourceUnavailableException.class).when(networkAclManager).replaceNetworkACL(Mockito.any(NetworkACL.class), Mockito.any(NetworkVO.class));
@@ -261,7 +275,7 @@ public void createAclListForNetworkAndReturnAclListIdTestAclNetworkIsCreatedButN
261275
@Test
262276
public void createAclListForNetworkAndReturnAclListIdTestAclIsCreatedAndAppliedWithSuccess() throws ResourceUnavailableException {
263277
Mockito.doReturn(true).when(networkModelMock).areServicesSupportedByNetworkOffering(networkOfferingMockId, Network.Service.NetworkACL);
264-
Mockito.doReturn(Mockito.mock(Vpc.class)).when(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
278+
Mockito.doReturn(Mockito.mock(Vpc.class)).when(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
265279

266280
NetworkACL networkAclMock = Mockito.mock(NetworkACL.class);
267281
Long expectedNetworkAclId = 5L;
@@ -339,7 +353,7 @@ public void validateNetworkAclTestAclDefaulDeny() {
339353
@Test(expected = InvalidParameterValueException.class)
340354
public void validateNetworkAclTestAclNotDefaulWithoutVpc() {
341355
Mockito.when(networkAclMock.getId()).thenReturn(3L);
342-
Mockito.doReturn(null).when(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
356+
Mockito.doReturn(null).when(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
343357
;
344358

345359
networkAclServiceImpl.validateNetworkAcl(networkAclMock);
@@ -357,13 +371,13 @@ public void validateNetworkAclTestAclNotDefaulWithVpc() {
357371
Mockito.when(networkAclMock.getId()).thenReturn(3L);
358372
Mockito.when(networkAclMock.getVpcId()).thenReturn(networkMockVpcMockId);
359373

360-
Mockito.doReturn(Mockito.mock(Vpc.class)).when(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
361-
Mockito.doNothing().when(AccountManager).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class));
374+
Mockito.doReturn(Mockito.mock(Vpc.class)).when(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
375+
Mockito.doNothing().when(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class));
362376

363377
networkAclServiceImpl.validateNetworkAcl(networkAclMock);
364378

365-
Mockito.verify(EntityManagerMock).findById(Vpc.class, networkMockVpcMockId);
366-
Mockito.verify(AccountManager).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class));
379+
Mockito.verify(entityManagerMock).findById(Vpc.class, networkMockVpcMockId);
380+
Mockito.verify(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class));
367381

368382
PowerMockito.verifyStatic();
369383
CallContext.current();
@@ -808,4 +822,60 @@ public void transferDataToNetworkAclRulePojoTestAllValuesWithUpdateData() {
808822
Mockito.verify(networkAclServiceImpl).validateAndCreateNetworkAclRuleAction("deny");
809823
}
810824

825+
@Test
826+
@PrepareForTest(CallContext.class)
827+
public void updateNetworkACLTestParametersNotNull() {
828+
String name = "name";
829+
String description = "desc";
830+
String customId = "customId";
831+
832+
Mockito.when(updateNetworkACLListCmdMock.getName()).thenReturn(name);
833+
Mockito.when(updateNetworkACLListCmdMock.getDescription()).thenReturn(description);
834+
Mockito.when(updateNetworkACLListCmdMock.getCustomId()).thenReturn(customId);
835+
Mockito.when(updateNetworkACLListCmdMock.getId()).thenReturn(networkAclListId);
836+
Mockito.when(updateNetworkACLListCmdMock.getDisplay()).thenReturn(false);
837+
838+
networkAclServiceImpl.updateNetworkACL(updateNetworkACLListCmdMock);
839+
840+
InOrder inOrder = Mockito.inOrder(networkAclDaoMock, entityManagerMock, entityManagerMock, accountManagerMock, networkACLVOMock);
841+
842+
inOrder.verify(networkAclDaoMock).findById(networkAclListId);
843+
inOrder.verify(entityManagerMock).findById(Mockito.eq(Vpc.class), Mockito.anyLong());
844+
inOrder.verify(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class));
845+
846+
inOrder.verify(networkACLVOMock).setName(name);
847+
inOrder.verify(networkACLVOMock).setDescription(description);
848+
inOrder.verify(networkACLVOMock).setUuid(customId);
849+
inOrder.verify(networkACLVOMock).setDisplay(false);
850+
851+
inOrder.verify(networkAclDaoMock).update(networkAclListId, networkACLVOMock);
852+
inOrder.verify(networkAclDaoMock).findById(networkAclListId);
853+
}
854+
855+
@Test
856+
@PrepareForTest(CallContext.class)
857+
public void updateNetworkACLTestParametersWithNullValues() {
858+
Mockito.when(updateNetworkACLListCmdMock.getName()).thenReturn(null);
859+
Mockito.when(updateNetworkACLListCmdMock.getDescription()).thenReturn(null);
860+
Mockito.when(updateNetworkACLListCmdMock.getCustomId()).thenReturn(null);
861+
Mockito.when(updateNetworkACLListCmdMock.getId()).thenReturn(networkAclListId);
862+
Mockito.when(updateNetworkACLListCmdMock.getDisplay()).thenReturn(null);
863+
864+
networkAclServiceImpl.updateNetworkACL(updateNetworkACLListCmdMock);
865+
866+
InOrder inOrder = Mockito.inOrder(networkAclDaoMock, entityManagerMock, entityManagerMock, accountManagerMock, networkACLVOMock);
867+
868+
inOrder.verify(networkAclDaoMock).findById(networkAclListId);
869+
inOrder.verify(entityManagerMock).findById(Mockito.eq(Vpc.class), Mockito.anyLong());
870+
inOrder.verify(accountManagerMock).checkAccess(Mockito.any(Account.class), Mockito.isNull(AccessType.class), Mockito.eq(true), Mockito.any(Vpc.class));
871+
872+
Mockito.verify(networkACLVOMock, Mockito.times(0)).setName(null);
873+
inOrder.verify(networkACLVOMock, Mockito.times(0)).setDescription(null);
874+
inOrder.verify(networkACLVOMock, Mockito.times(0)).setUuid(null);
875+
inOrder.verify(networkACLVOMock, Mockito.times(0)).setDisplay(false);
876+
877+
inOrder.verify(networkAclDaoMock).update(networkAclListId, networkACLVOMock);
878+
inOrder.verify(networkAclDaoMock).findById(networkAclListId);
879+
}
880+
811881
}

ui/l10n/ar.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ var dictionary = {
318318
"label.add.accounts": "إضافة حسابات",
319319
"label.add.accounts.to": "إضافة حسابات إلى",
320320
"label.add.acl.list": "Add ACL List",
321+
"label.edit.acl.list": "Edit ACL List",
321322
"label.add.affinity.group": "Add new affinity group",
322323
"label.add.baremetal.dhcp.device": "Add Baremetal DHCP Device",
323324
"label.add.baremetal.rack.configuration": "Add Baremetal Rack Configuration",

ui/l10n/ca.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ var dictionary = {
318318
"label.add.accounts": "Afegir comptes",
319319
"label.add.accounts.to": "Afegir comptes a",
320320
"label.add.acl.list": "Add ACL List",
321+
"label.edit.acl.list": "Edit ACL List",
321322
"label.add.affinity.group": "Add new affinity group",
322323
"label.add.baremetal.dhcp.device": "Add Baremetal DHCP Device",
323324
"label.add.baremetal.rack.configuration": "Add Baremetal Rack Configuration",

ui/l10n/de_DE.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ var dictionary = {
318318
"label.add.accounts": "Konten hinzufügen",
319319
"label.add.accounts.to": "Konten hinzufügen zu",
320320
"label.add.acl.list": "ACL-Liste hinzufügen",
321+
"label.edit.acl.list": "Edit ACL List",
321322
"label.add.affinity.group": "Neue Affinitätsgruppe hinzufügen",
322323
"label.add.baremetal.dhcp.device": "Baremetal DHCP-Gerät hinzufügen",
323324
"label.add.baremetal.rack.configuration": "Baremetal Rackkonfiguration hinzufügen",

ui/l10n/en.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ var dictionary = {
320320
"label.add.accounts":"Add accounts",
321321
"label.add.accounts.to":"Add accounts to",
322322
"label.add.acl.list":"Add ACL List",
323+
"label.edit.acl.list": "Edit ACL List",
323324
"label.add.affinity.group":"Add new affinity group",
324325
"label.add.baremetal.dhcp.device":"Add Baremetal DHCP Device",
325326
"label.add.baremetal.rack.configuration":"Add Baremetal Rack Configuration",

0 commit comments

Comments
 (0)