Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit 8cfa7d7

Browse files
committed
#239 Optimized role deployment
A role that doesn't have references to other roles won't be deployed twice now
1 parent 3ebcf5a commit 8cfa7d7

File tree

4 files changed

+66
-11
lines changed

4 files changed

+66
-11
lines changed

src/main/java/com/marklogic/appdeployer/command/AbstractCommand.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ protected SaveReceipt saveResource(ResourceManager mgr, CommandContext context,
137137
String payload = copyFileToString(f, context);
138138
mgr = adjustResourceManagerForPayload(mgr, context, payload);
139139
payload = adjustPayloadBeforeSavingResource(mgr, context, f, payload);
140+
141+
// A subclass may decide that the resource shouldn't be saved by returning a null payload
142+
if (payload == null) {
143+
return null;
144+
}
145+
140146
SaveReceipt receipt = mgr.save(payload);
141147
if (storeResourceIdsAsCustomTokens) {
142148
storeTokenForResourceId(receipt, context);
@@ -147,6 +153,8 @@ protected SaveReceipt saveResource(ResourceManager mgr, CommandContext context,
147153
/**
148154
* Allow subclass to override this in order to fiddle with the payload before it's saved; called by saveResource.
149155
*
156+
* A subclass can return null from this method to indicate that the resource should not be saved.
157+
*
150158
* @param mgr
151159
* @param context
152160
* @param f

src/main/java/com/marklogic/appdeployer/command/AbstractResourceCommand.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ protected File[] listFilesInDirectory(File resourceDir, CommandContext context)
110110
*/
111111
protected void afterResourceSaved(ResourceManager mgr, CommandContext context, File resourceFile,
112112
SaveReceipt receipt) {
113+
if (receipt == null) {
114+
return;
115+
}
113116
ResponseEntity<String> response = receipt.getResponse();
114117
if (response != null) {
115118
HttpHeaders headers = response.getHeaders();

src/main/java/com/marklogic/appdeployer/command/security/DeployRolesCommand.java

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,51 +11,91 @@
1111
import com.marklogic.mgmt.resource.security.RoleManager;
1212

1313
import java.io.File;
14+
import java.util.HashSet;
15+
import java.util.Set;
1416

1517
public class DeployRolesCommand extends AbstractResourceCommand {
1618

1719
// Used internally
1820
private boolean removeRolesAndPermissionsDuringDeployment = false;
1921
private ResourceMapper resourceMapper;
22+
private Set<String> roleNamesThatDontNeedToBeRedeployed;
2023

2124
public DeployRolesCommand() {
2225
setExecuteSortOrder(SortOrderConstants.DEPLOY_ROLES);
2326
setUndoSortOrder(SortOrderConstants.DELETE_ROLES);
2427
}
2528

2629
/**
27-
* The set of roles is processed twice. The first time, the roles are saved without any permissions or dependent roles.
28-
* This is to avoid issues where the roles depend on each other or on themselves. The second time, the roles are
29-
* saved with permissions and dependent roles, which is guaranteed to work now that the roles have all been created.
30+
* The set of roles is processed twice. The first time, the roles are saved without any default permissions or references to other roles.
31+
* This is to avoid issues where the roles refer to each other or to themselves (via default permissions). The second time, the roles are
32+
* saved with permissions and references to other roles, which is guaranteed to work now that the roles have all been created.
3033
*
3134
* @param context
3235
*/
3336
@Override
3437
public void execute(CommandContext context) {
3538
removeRolesAndPermissionsDuringDeployment = true;
3639
if (logger.isInfoEnabled()) {
37-
logger.info("Deploying roles without any permissions or dependent roles");
40+
logger.info("Deploying roles minus their default permissions and references to roles");
3841
}
42+
roleNamesThatDontNeedToBeRedeployed = new HashSet<>();
3943
super.execute(context);
4044
if (logger.isInfoEnabled()) {
41-
logger.info("Deploying roles with permissions and dependent roles");
45+
logger.info("Redeploying roles that have default permissions and/or references to roles");
4246
}
4347
removeRolesAndPermissionsDuringDeployment = false;
4448
super.execute(context);
4549
}
4650

51+
/**
52+
* If this is the first time roles are being deployed by this command - indicated by the removeRolesAndPermissionsDuringDeployment
53+
* class variable - then each payload is modified so that default permissions and role references are not included,
54+
* thus ensuring that the role can be created successfully.
55+
*
56+
* If this is the second time that roles are being deployed by this command, then the entire payload is sent. However,
57+
* if the role doesn't have any default permissions or role references, it will not be deployed a second time, as
58+
* there was nothing missing from the first deployment of the role.
59+
*
60+
* @param mgr
61+
* @param context
62+
* @param f
63+
* @param payload
64+
* @return
65+
*/
4766
@Override
4867
protected String adjustPayloadBeforeSavingResource(ResourceManager mgr, CommandContext context, File f, String payload) {
4968
payload = super.adjustPayloadBeforeSavingResource(mgr, context, f, payload);
69+
70+
if (resourceMapper == null) {
71+
API api = new API(context.getManageClient(), context.getAdminManager());
72+
resourceMapper = new DefaultResourceMapper(api);
73+
}
74+
75+
Role role = resourceMapper.readResource(payload, Role.class);
76+
77+
// Is this the first time the roles are being deployed?
5078
if (removeRolesAndPermissionsDuringDeployment) {
51-
if (resourceMapper == null) {
52-
API api = new API(context.getManageClient(), context.getAdminManager());
53-
resourceMapper = new DefaultResourceMapper(api);
79+
if (role.hasPermissionsOrRoles()) {
80+
role.clearPermissionsAndRoles();
81+
return role.getJson();
82+
} else {
83+
roleNamesThatDontNeedToBeRedeployed.add(role.getRoleName());
84+
return payload;
85+
}
86+
}
87+
// Else it's the second time roles are being deployed, but no need to deploy a role if it doesn't have any default permissions or role references
88+
else if (roleNamesThatDontNeedToBeRedeployed.contains(role.getRoleName())) {
89+
if (logger.isInfoEnabled()) {
90+
logger.info("Not redeploying role " + role.getRoleName() + ", as it does not have any default permissions or references to other roles");
5491
}
55-
Role role = resourceMapper.readResource(payload, Role.class);
56-
role.clearPermissionsAndRoles();
57-
return role.getJson();
92+
return null;
93+
}
94+
// Else log a message to indicate that the role is being redeployed
95+
else if (logger.isInfoEnabled()) {
96+
logger.info("Redeploying role " + role.getRoleName() + " with default permissions and references to other roles included");
5897
}
98+
5999
return payload;
60100
}
61101

src/main/java/com/marklogic/mgmt/api/security/Role.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ public Role(API api, String roleName) {
5555
this.roleName = roleName;
5656
}
5757

58+
public boolean hasPermissionsOrRoles() {
59+
return (role != null && !role.isEmpty()) || (permission != null && !permission.isEmpty());
60+
}
61+
5862
public void clearPermissionsAndRoles() {
5963
if (role != null) {
6064
role.clear();

0 commit comments

Comments
 (0)