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

Commit e0413a3

Browse files
committed
#438 Can build a list of commands for deploying to a replica cluster
1 parent f544082 commit e0413a3

File tree

4 files changed

+167
-74
lines changed

4 files changed

+167
-74
lines changed

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

Lines changed: 89 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -51,147 +51,162 @@
5151
*/
5252
public class CommandMapBuilder {
5353

54+
/**
55+
* @return a map of all commands relevant to deploying an application, including those that can write data to a
56+
* database and thus should only be run against a cluster that is not a replica cluster
57+
*/
5458
public Map<String, List<Command>> buildCommandMap() {
5559
Map<String, List<Command>> map = new HashMap<>();
60+
addCommandsThatDoNotWriteToDatabases(map);
61+
addCommandsThatWriteToDatabases(map);
62+
return map;
63+
}
5664

57-
// Security
58-
List<Command> securityCommands = new ArrayList<Command>();
59-
securityCommands.add(new DeployRolesCommand());
60-
securityCommands.add(new DeployUsersCommand());
61-
securityCommands.add(new DeployAmpsCommand());
62-
securityCommands.add(new DeployCertificateTemplatesCommand());
63-
securityCommands.add(new DeployCertificateAuthoritiesCommand());
64-
securityCommands.add(new InsertCertificateHostsTemplateCommand());
65-
securityCommands.add(new DeployExternalSecurityCommand());
66-
securityCommands.add(new DeployPrivilegesCommand());
67-
securityCommands.add(new DeployPrivilegeRolesCommand());
68-
securityCommands.add(new DeployProtectedCollectionsCommand());
69-
securityCommands.add(new DeployProtectedPathsCommand());
70-
securityCommands.add(new DeployQueryRolesetsCommand());
71-
map.put("mlSecurityCommands", securityCommands);
65+
/**
66+
* For deploying to a replica cluster, care must be taken not to run any command that will write to a database that
67+
* is likely to have database replication configured for it. This then returns a map of commands that are known not
68+
* to write any data to databases. The security commands are an exception though, as it's typical for the Security
69+
* database to not have database replication configured for it. If this is not the case for a user, the user can
70+
* still use this method and simply remove the commands that write to the Security database.
71+
*
72+
* @return
73+
*/
74+
public Map<String, List<Command>> buildCommandMapForReplicaCluster() {
75+
Map<String, List<Command>> map = new HashMap<>();
76+
addCommandsThatDoNotWriteToDatabases(map);
77+
return map;
78+
}
79+
80+
/**
81+
* Same as buildCommandMapForReplicaCluster, but returns a list of all the commands.
82+
*
83+
* @return
84+
*/
85+
public List<Command> getCommandsForReplicaCluster() {
86+
return buildCommandMapForReplicaCluster()
87+
.values()
88+
.stream().reduce(new ArrayList<>(), (a, b) -> {
89+
a.addAll(b);
90+
return a;
91+
});
92+
}
7293

73-
// Cluster
94+
private void addCommandsThatDoNotWriteToDatabases(Map<String, List<Command>> map) {
7495
List<Command> clusterCommands = new ArrayList<Command>();
7596
clusterCommands.add(new ModifyLocalClusterCommand());
7697
map.put("mlClusterCommands", clusterCommands);
7798

78-
// Configurations
7999
List<Command> configurationCommands = new ArrayList<>();
80100
configurationCommands.add(new DeployConfigurationsCommand());
81101
map.put("mlConfigurationCommands", configurationCommands);
82102

83-
// Databases
84103
List<Command> dbCommands = new ArrayList<Command>();
85104
dbCommands.add(new DeployOtherDatabasesCommand());
86105
map.put("mlDatabaseCommands", dbCommands);
87106

88-
// Database rebalancer
107+
List<Command> forestCommands = new ArrayList<Command>();
108+
forestCommands.add(new DeployCustomForestsCommand());
109+
map.put("mlForestCommands", forestCommands);
110+
111+
List<Command> replicaCommands = new ArrayList<Command>();
112+
replicaCommands.add(new ConfigureForestReplicasCommand());
113+
map.put("mlForestReplicaCommands", replicaCommands);
114+
115+
List<Command> groupCommands = new ArrayList<Command>();
116+
groupCommands.add(new DeployGroupsCommand());
117+
map.put("mlGroupCommands", groupCommands);
118+
119+
List<Command> hostCommands = new ArrayList<Command>();
120+
hostCommands.add(new AssignHostsToGroupsCommand());
121+
map.put("mlHostCommands", hostCommands);
122+
123+
List<Command> mimetypeCommands = new ArrayList<Command>();
124+
mimetypeCommands.add(new DeployMimetypesCommand());
125+
map.put("mlMimetypeCommands", mimetypeCommands);
126+
127+
List<Command> pluginCommands = new ArrayList<>();
128+
pluginCommands.add(new InstallPluginsCommand());
129+
map.put("mlPluginCommands", pluginCommands);
130+
89131
List<Command> rebalancerCommands = new ArrayList<>();
90132
rebalancerCommands.add(new DeployPartitionsCommand());
91133
rebalancerCommands.add(new DeployPartitionQueriesCommand());
92134
map.put("mlRebalancerCommands", rebalancerCommands);
93135

94-
// Schemas
95-
List<Command> schemaCommands = new ArrayList<>();
96-
schemaCommands.add(new LoadSchemasCommand());
97-
map.put("mlSchemaCommands", schemaCommands);
98-
99-
// REST API instance creation
100136
List<Command> restApiCommands = new ArrayList<>();
101137
restApiCommands.add(new DeployRestApiServersCommand());
102138
map.put("mlRestApiCommands", restApiCommands);
103139

104-
// App servers
140+
List<Command> securityCommands = new ArrayList<Command>();
141+
securityCommands.add(new DeployRolesCommand());
142+
securityCommands.add(new DeployUsersCommand());
143+
securityCommands.add(new DeployAmpsCommand());
144+
securityCommands.add(new DeployCertificateTemplatesCommand());
145+
securityCommands.add(new DeployCertificateAuthoritiesCommand());
146+
securityCommands.add(new InsertCertificateHostsTemplateCommand());
147+
securityCommands.add(new DeployExternalSecurityCommand());
148+
securityCommands.add(new DeployPrivilegesCommand());
149+
securityCommands.add(new DeployPrivilegeRolesCommand());
150+
securityCommands.add(new DeployProtectedCollectionsCommand());
151+
securityCommands.add(new DeployProtectedPathsCommand());
152+
securityCommands.add(new DeployQueryRolesetsCommand());
153+
map.put("mlSecurityCommands", securityCommands);
154+
105155
List<Command> serverCommands = new ArrayList<>();
106156
serverCommands.add(new DeployOtherServersCommand());
107157
serverCommands.add(new UpdateRestApiServersCommand());
108158
map.put("mlServerCommands", serverCommands);
109159

110-
// Modules
111-
List<Command> moduleCommands = new ArrayList<>();
112-
moduleCommands.add(new LoadModulesCommand());
113-
moduleCommands.add(new DeleteTestModulesCommand());
114-
map.put("mlModuleCommands", moduleCommands);
160+
List<Command> taskCommands = new ArrayList<Command>();
161+
taskCommands.add(new DeployScheduledTasksCommand());
162+
taskCommands.add(new UpdateTaskServerCommand());
163+
map.put("mlTaskCommands", taskCommands);
164+
}
115165

116-
// Alerting
166+
private void addCommandsThatWriteToDatabases(Map<String, List<Command>> map) {
117167
List<Command> alertCommands = new ArrayList<Command>();
118168
alertCommands.add(new DeployAlertConfigsCommand());
119169
alertCommands.add(new DeployAlertActionsCommand());
120170
alertCommands.add(new DeployAlertRulesCommand());
121171
map.put("mlAlertCommands", alertCommands);
122172

123-
// CPF
124173
List<Command> cpfCommands = new ArrayList<Command>();
125174
cpfCommands.add(new DeployCpfConfigsCommand());
126175
cpfCommands.add(new DeployDomainsCommand());
127176
cpfCommands.add(new DeployPipelinesCommand());
128177
map.put("mlCpfCommands", cpfCommands);
129178

130-
// Data
131179
List<Command> dataCommands = new ArrayList<>();
132180
dataCommands.add(new LoadDataCommand());
133181
map.put("mlDataCommands", dataCommands);
134182

135-
// Flexrep
136183
List<Command> flexrepCommands = new ArrayList<Command>();
137184
flexrepCommands.add(new DeployConfigsCommand());
138185
flexrepCommands.add(new DeployTargetsCommand());
139186
flexrepCommands.add(new DeployFlexrepCommand());
140187
map.put("mlFlexrepCommands", flexrepCommands);
141188

142-
// Groups
143-
List<Command> groupCommands = new ArrayList<Command>();
144-
groupCommands.add(new DeployGroupsCommand());
145-
map.put("mlGroupCommands", groupCommands);
146-
147-
List<Command> mimetypeCommands = new ArrayList<Command>();
148-
mimetypeCommands.add(new DeployMimetypesCommand());
149-
map.put("mlMimetypeCommands", mimetypeCommands);
150-
151-
// Hosts
152-
List<Command> hostCommands = new ArrayList<Command>();
153-
hostCommands.add(new AssignHostsToGroupsCommand());
154-
map.put("mlAssignHostsToGroups", hostCommands);
155-
156-
// Forests
157-
List<Command> forestCommands = new ArrayList<Command>();
158-
forestCommands.add(new DeployCustomForestsCommand());
159-
map.put("mlForestCommands", forestCommands);
160-
161-
// Forest replicas
162-
List<Command> replicaCommands = new ArrayList<Command>();
163-
replicaCommands.add(new ConfigureForestReplicasCommand());
164-
map.put("mlForestReplicaCommands", replicaCommands);
165-
166-
// Plugins
167-
List<Command> pluginCommands = new ArrayList<>();
168-
pluginCommands.add(new InstallPluginsCommand());
169-
map.put("mlPluginCommands", pluginCommands);
189+
List<Command> moduleCommands = new ArrayList<>();
190+
moduleCommands.add(new LoadModulesCommand());
191+
moduleCommands.add(new DeleteTestModulesCommand());
192+
map.put("mlModuleCommands", moduleCommands);
170193

171-
// Tasks
172-
List<Command> taskCommands = new ArrayList<Command>();
173-
taskCommands.add(new DeployScheduledTasksCommand());
174-
taskCommands.add(new UpdateTaskServerCommand());
175-
map.put("mlTaskCommands", taskCommands);
194+
List<Command> schemaCommands = new ArrayList<>();
195+
schemaCommands.add(new LoadSchemasCommand());
196+
map.put("mlSchemaCommands", schemaCommands);
176197

177-
// Temporal
178198
List<Command> temporalCommands = new ArrayList<>();
179199
temporalCommands.add(new DeployTemporalAxesCommand());
180200
temporalCommands.add(new DeployTemporalCollectionsCommand());
181201
temporalCommands.add(new DeployTemporalCollectionsLSQTCommand());
182202
map.put("mlTemporalCommands", temporalCommands);
183203

184-
// Triggers
185204
List<Command> triggerCommands = new ArrayList<Command>();
186205
triggerCommands.add(new DeployTriggersCommand());
187206
map.put("mlTriggerCommands", triggerCommands);
188207

189-
190-
// SQL Views
191208
List<Command> viewCommands = new ArrayList<Command>();
192209
viewCommands.add(new DeployViewSchemasCommand());
193210
map.put("mlViewCommands", viewCommands);
194-
195-
return map;
196211
}
197212
}

src/main/java/com/marklogic/appdeployer/impl/SimpleAppDeployer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public SimpleAppDeployer(Command... commandArray) {
1919
buildModifiableCommandList(commandArray);
2020
}
2121

22+
public SimpleAppDeployer(List<Command> commands) {
23+
this.commands = commands;
24+
}
25+
2226
public SimpleAppDeployer(ManageClient manageClient, AdminManager adminManager, Command... commandArray) {
2327
super(manageClient, adminManager);
2428
buildModifiableCommandList(commandArray);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.marklogic.appdeployer.command;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.stream.Stream;
9+
10+
import static org.junit.jupiter.api.Assertions.*;
11+
12+
public class CommandMapBuilderTest {
13+
14+
CommandMapBuilder commandMapBuilder = new CommandMapBuilder();
15+
16+
@Test
17+
void buildCommandsForNonReplicaCluster() {
18+
Map<String, List<Command>> map = commandMapBuilder.buildCommandMap();
19+
verifyCommandsThatDoNotWriteDataExist(map);
20+
verifyExistenceOfCommandsThatDoWriteData(map, true);
21+
}
22+
23+
@Test
24+
void buildCommandsForReplicaCluster() {
25+
Map<String, List<Command>> map = commandMapBuilder.buildCommandMapForReplicaCluster();
26+
verifyCommandsThatDoNotWriteDataExist(map);
27+
verifyExistenceOfCommandsThatDoWriteData(map, false);
28+
29+
List<Command> mapCommands = map.values().stream().reduce(new ArrayList<>(), (a, b) -> {a.addAll(b); return a;});
30+
31+
List<Command> commands = commandMapBuilder.getCommandsForReplicaCluster();
32+
assertEquals(mapCommands.size(), commands.size(), "The convenience method for getting a list of commands " +
33+
"should have the same number of commands as the map of commands that we just validated");
34+
}
35+
36+
private void verifyCommandsThatDoNotWriteDataExist(Map<String, List<Command>> map) {
37+
Stream.of("mlClusterCommands", "mlConfigurationCommands", "mlDatabaseCommands", "mlForestCommands", "mlForestReplicaCommands",
38+
"mlGroupCommands", "mlHostCommands", "mlMimetypeCommands", "mlPluginCommands", "mlRebalancerCommands",
39+
"mlRestApiCommands", "mlSecurityCommands", "mlServerCommands", "mlTaskCommands"
40+
).forEach(groupName -> {
41+
assertTrue(map.containsKey(groupName));
42+
});
43+
}
44+
45+
private void verifyExistenceOfCommandsThatDoWriteData(Map<String, List<Command>> map, boolean shouldExist) {
46+
Stream.of("mlAlertCommands", "mlCpfCommands", "mlDataCommands", "mlFlexrepCommands", "mlModuleCommands",
47+
"mlSchemaCommands", "mlTemporalCommands", "mlTriggerCommands", "mlViewCommands"
48+
).forEach(groupName -> {
49+
if (shouldExist) {
50+
assertTrue(map.containsKey(groupName),
51+
"When deploying to a non-replica cluster (i.e. one that is not the target for database replication " +
52+
"from a master cluster), it is safe to execute commands that write data to a database");
53+
} else {
54+
assertFalse(map.containsKey(groupName),
55+
"When deploying to a replica cluster, a command that writes data to a database should not be " +
56+
"included in the list of commands to execute");
57+
}
58+
});
59+
}
60+
}

src/test/java/com/marklogic/appdeployer/impl/SimpleAppDeployerTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import org.junit.jupiter.api.BeforeEach;
88
import org.junit.jupiter.api.Test;
99

10+
import java.util.Arrays;
11+
1012
public class SimpleAppDeployerTest {
1113

1214
private SimpleAppDeployer deployer;
@@ -41,4 +43,16 @@ public void removeCommand() {
4143
assertEquals(dbCommand, deployer.removeCommand("DeployOtherDatabasesCommand"));
4244
assertTrue(deployer.getCommands().isEmpty());
4345
}
46+
47+
@Test
48+
void constructWithList() {
49+
deployer = new SimpleAppDeployer(Arrays.asList(new DeployOtherDatabasesCommand()));
50+
assertEquals(1, deployer.getCommands().size());
51+
}
52+
53+
@Test
54+
void constructWithArray() {
55+
deployer = new SimpleAppDeployer(new DeployOtherDatabasesCommand());
56+
assertEquals(1, deployer.getCommands().size());
57+
}
4458
}

0 commit comments

Comments
 (0)