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

Commit 0dba5c2

Browse files
committed
#168 Added support for replica forest properties
1 parent ae94320 commit 0dba5c2

File tree

7 files changed

+156
-18
lines changed

7 files changed

+156
-18
lines changed

src/main/java/com/marklogic/appdeployer/AppConfig.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
* Encapsulates common configuration properties for an application deployed to MarkLogic. These properties include not
2424
* just names of application resources - such as app servers and databases - but also connection information for loading
2525
* modules into an application as well as paths for modules and configuration files.
26-
* <p>
26+
*
2727
* An instance of this class is passed in as the main argument to the methods in the {@code AppDeployer} interface,
2828
* meaning that you're free to not just configure this as needed but also subclass it and add anything that you would
2929
* like.
30+
*
31+
* Additionally, the additionalProperties Map can used for storing any additional properties that a client of this class
32+
* may use, without having to define them as attributes of this class.
3033
*/
3134
public class AppConfig {
3235

@@ -118,6 +121,11 @@ public class AppConfig {
118121
// Comma-delimited string used for configuring forest replicas
119122
private String databaseNamesAndReplicaCounts;
120123

124+
// Configures the data-directory for replica forests built dynamically
125+
private String replicaForestDataDirectory;
126+
private String replicaForestLargeDataDirectory;
127+
private String replicaForestFastDataDirectory;
128+
121129
// Path to use for DeployFlexrepCommand
122130
private String flexrepPath;
123131

@@ -142,6 +150,8 @@ public class AppConfig {
142150

143151
private String[] resourceFilenamesToIgnore;
144152

153+
private Map<String, Object> additionalProperties = new HashMap<>();
154+
145155
public AppConfig() {
146156
this(DEFAULT_MODULES_PATH, DEFAULT_SCHEMAS_PATH);
147157
}
@@ -737,4 +747,36 @@ public boolean isNoRestServer() {
737747
public void setNoRestServer(boolean noRestServer) {
738748
this.noRestServer = noRestServer;
739749
}
750+
751+
public String getReplicaForestDataDirectory() {
752+
return replicaForestDataDirectory;
753+
}
754+
755+
public void setReplicaForestDataDirectory(String replicaForestDataDirectory) {
756+
this.replicaForestDataDirectory = replicaForestDataDirectory;
757+
}
758+
759+
public String getReplicaForestLargeDataDirectory() {
760+
return replicaForestLargeDataDirectory;
761+
}
762+
763+
public void setReplicaForestLargeDataDirectory(String replicaForestLargeDataDirectory) {
764+
this.replicaForestLargeDataDirectory = replicaForestLargeDataDirectory;
765+
}
766+
767+
public String getReplicaForestFastDataDirectory() {
768+
return replicaForestFastDataDirectory;
769+
}
770+
771+
public void setReplicaForestFastDataDirectory(String replicaForestFastDataDirectory) {
772+
this.replicaForestFastDataDirectory = replicaForestFastDataDirectory;
773+
}
774+
775+
public Map<String, Object> getAdditionalProperties() {
776+
return additionalProperties;
777+
}
778+
779+
public void setAdditionalProperties(Map<String, Object> additionalProperties) {
780+
this.additionalProperties = additionalProperties;
781+
}
740782
}

src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,24 @@ public AppConfig newAppConfig() {
158158
c.setDatabaseNamesAndReplicaCounts(prop);
159159
}
160160

161+
prop = getProperty("mlReplicaForestDataDirectory");
162+
if (prop != null) {
163+
logger.info("Replica forest data directory " + prop);
164+
c.setReplicaForestDataDirectory(prop);
165+
}
166+
167+
prop = getProperty("mlReplicaForestLargeDataDirectory");
168+
if (prop != null) {
169+
logger.info("Replica forest large data directory " + prop);
170+
c.setReplicaForestLargeDataDirectory(prop);
171+
}
172+
173+
prop = getProperty("mlReplicaForestFastDataDirectory");
174+
if (prop != null) {
175+
logger.info("Replica forest fast data directory " + prop);
176+
c.setReplicaForestFastDataDirectory(prop);
177+
}
178+
161179
/**
162180
* When undo is invoked on DeployDatabaseCommand (such as via mlUndeploy in ml-gradle), this controls whether
163181
* or not forests are deleted, or just their configuration is deleted. If mlDeleteReplicas is set to true, this

src/main/java/com/marklogic/appdeployer/command/forests/ConfigureForestReplicasCommand.java

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package com.marklogic.appdeployer.command.forests;
22

3+
import com.marklogic.appdeployer.AppConfig;
34
import com.marklogic.appdeployer.command.AbstractUndoableCommand;
45
import com.marklogic.appdeployer.command.CommandContext;
56
import com.marklogic.appdeployer.command.SortOrderConstants;
7+
import com.marklogic.mgmt.api.API;
8+
import com.marklogic.mgmt.api.forest.Forest;
9+
import com.marklogic.mgmt.api.forest.ForestReplica;
610
import com.marklogic.mgmt.databases.DatabaseManager;
711
import com.marklogic.mgmt.forests.ForestManager;
812
import com.marklogic.mgmt.forests.ForestStatus;
913
import com.marklogic.mgmt.hosts.HostManager;
1014

15+
import java.util.ArrayList;
1116
import java.util.HashMap;
1217
import java.util.List;
1318
import java.util.Map;
@@ -84,7 +89,7 @@ public void execute(CommandContext context) {
8489
for (String forestName : forestNamesAndReplicaCounts.keySet()) {
8590
int replicaCount = forestNamesAndReplicaCounts.get(forestName);
8691
if (replicaCount > 0) {
87-
configureReplicaForests(forestName, replicaCount, hostIds, forestMgr);
92+
configureReplicaForests(forestName, replicaCount, hostIds, context, forestMgr);
8893
}
8994
}
9095
}
@@ -130,21 +135,20 @@ protected void deleteReplicas(String forestName, ForestManager forestMgr) {
130135

131136
/**
132137
* For the given database, find all of its primary forests. Then for each primary forest, just call
133-
* configureReplicaForests? And that should be smart enough to say - if the primary forest already has replicas,
138+
* configureReplicaForests. And that should be smart enough to say - if the primary forest already has replicas,
134139
* then don't do anything.
135140
*
136141
* @param databaseName
137142
* @param replicaCount
138143
* @param hostIds
139144
*/
140145
protected void configureDatabaseReplicaForests(String databaseName, int replicaCount, List<String> hostIds,
141-
CommandContext context) {
146+
CommandContext context) {
142147
ForestManager forestMgr = new ForestManager(context.getManageClient());
143148
DatabaseManager dbMgr = new DatabaseManager(context.getManageClient());
144149
List<String> forestNames = dbMgr.getForestNames(databaseName);
145-
logger.info("Forests: " + forestNames);
146150
for (String name : forestNames) {
147-
configureReplicaForests(name, replicaCount, hostIds, forestMgr);
151+
configureReplicaForests(name, replicaCount, hostIds, context, forestMgr);
148152
}
149153
}
150154

@@ -155,10 +159,11 @@ protected void configureDatabaseReplicaForests(String databaseName, int replicaC
155159
* @param forestIdOrName
156160
* @param replicaCount
157161
* @param hostIds
162+
* @param context
158163
* @param forestMgr
159164
*/
160165
protected void configureReplicaForests(String forestIdOrName, int replicaCount, List<String> hostIds,
161-
ForestManager forestMgr) {
166+
CommandContext context, ForestManager forestMgr) {
162167
ForestStatus status = forestMgr.getForestStatus(forestIdOrName);
163168
if (!status.isPrimary()) {
164169
logger.info(format("Forest %s is not a primary forest, so not configuring replica forests", forestIdOrName));
@@ -169,12 +174,9 @@ protected void configureReplicaForests(String forestIdOrName, int replicaCount,
169174
return;
170175
}
171176

172-
Map<String, String> replicaNamesAndHostIds = createReplicaForests(forestIdOrName, replicaCount, hostIds, forestMgr);
173-
logger.info(format("Configuring forest replicas for primary forest %s", forestIdOrName));
174-
if (!replicaNamesAndHostIds.isEmpty()) {
175-
forestMgr.setReplicas(forestIdOrName, replicaNamesAndHostIds);
176-
}
177-
logger.info(format("Finished configuring forest replicas for primary forest %s", forestIdOrName));
177+
logger.info(format("Creating forest replicas for primary forest %s", forestIdOrName));
178+
createReplicaForests(forestIdOrName, replicaCount, hostIds, context, forestMgr);
179+
logger.info(format("Finished creating forest replicas for primary forest %s", forestIdOrName));
178180
}
179181

180182
/**
@@ -184,12 +186,20 @@ protected void configureReplicaForests(String forestIdOrName, int replicaCount,
184186
* @param forestIdOrName
185187
* @param replicaCount
186188
* @param hostIds
189+
* @param context
187190
* @param forestMgr
188191
* @return a map where the keys are replica forest names, and the value of each key is the ID of the host that
189192
* the replica was created on
190193
*/
191194
protected Map<String, String> createReplicaForests(String forestIdOrName, int replicaCount, List<String> hostIds,
192-
ForestManager forestMgr) {
195+
CommandContext context, ForestManager forestMgr) {
196+
197+
// Using the Forest class to generate JSON
198+
API api = new API(context.getManageClient());
199+
Forest forest = new Forest(api, null);
200+
List<ForestReplica> replicas = new ArrayList<>();
201+
forest.setForestReplica(replicas);
202+
193203
String primaryForestHostId = forestMgr.getHostId(forestIdOrName);
194204
Map<String, String> replicaNamesAndHostIds = new HashMap<>();
195205
int size = hostIds.size();
@@ -203,15 +213,28 @@ protected Map<String, String> createReplicaForests(String forestIdOrName, int re
203213
}
204214
String replicaHostId = hostIds.get(nextReplicaHostIndex);
205215
String name = forestIdOrName + "-replica-" + j;
206-
forestMgr.createJsonForestWithName(name, replicaHostId);
216+
replicas.add(buildForestReplica(name, replicaHostId, context.getAppConfig()));
207217
replicaNamesAndHostIds.put(name, replicaHostId);
208218
nextReplicaHostIndex++;
209219
}
210220
}
211221
}
222+
223+
String json = forest.getJson();
224+
context.getManageClient().putJson(forestMgr.getPropertiesPath(forestIdOrName), json);
212225
return replicaNamesAndHostIds;
213226
}
214227

228+
protected ForestReplica buildForestReplica(String name, String replicaHostId, AppConfig appConfig) {
229+
ForestReplica replica = new ForestReplica();
230+
replica.setHost(replicaHostId);
231+
replica.setReplicaName(name);
232+
replica.setDataDirectory(appConfig.getReplicaForestDataDirectory());
233+
replica.setLargeDataDirectory(appConfig.getReplicaForestLargeDataDirectory());
234+
replica.setFastDataDirectory(appConfig.getReplicaForestFastDataDirectory());
235+
return replica;
236+
}
237+
215238
public Map<String, Integer> getForestNamesAndReplicaCounts() {
216239
return forestNamesAndReplicaCounts;
217240
}

src/main/java/com/marklogic/mgmt/api/forest/Forest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class Forest extends Resource {
2525
private List<String> failoverHost;
2626
private List<ForestBackup> forestBackup;
2727
private List<DatabaseReplication> databaseReplication;
28+
private List<ForestReplica> forestReplica;
2829

2930
public Forest() {
3031
}
@@ -191,4 +192,12 @@ public Boolean getRebalancerEnable() {
191192
public Boolean getFailoverEnable() {
192193
return failoverEnable;
193194
}
195+
196+
public List<ForestReplica> getForestReplica() {
197+
return forestReplica;
198+
}
199+
200+
public void setForestReplica(List<ForestReplica> forestReplica) {
201+
this.forestReplica = forestReplica;
202+
}
194203
}

src/test/java/com/marklogic/appdeployer/DefaultAppConfigFactoryTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ public void allProperties() {
7979
p.setProperty("mlGenerateExtractionTemplate", "false");
8080
p.setProperty("mlResourceFilenamesToIgnore", "role1.json,role2.xml");
8181

82+
p.setProperty("mlDatabaseNamesAndReplicaCounts", "Documents,1,Security,2");
83+
p.setProperty("mlReplicaForestDataDirectory", "/var/data");
84+
p.setProperty("mlReplicaForestFastDataDirectory", "/var/fast");
85+
p.setProperty("mlReplicaForestLargeDataDirectory", "/var/large");
86+
8287
sut = new DefaultAppConfigFactory(new SimplePropertySource(p));
8388
AppConfig config = sut.newAppConfig();
8489

@@ -124,6 +129,11 @@ public void allProperties() {
124129

125130
assertEquals("role1.json", config.getResourceFilenamesToIgnore()[0]);
126131
assertEquals("role2.xml", config.getResourceFilenamesToIgnore()[1]);
132+
133+
assertEquals("Documents,1,Security,2", config.getDatabaseNamesAndReplicaCounts());
134+
assertEquals("/var/data", config.getReplicaForestDataDirectory());
135+
assertEquals("/var/fast", config.getReplicaForestFastDataDirectory());
136+
assertEquals("/var/large", config.getReplicaForestLargeDataDirectory());
127137
}
128138

129139
/**
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.marklogic.appdeployer.command.forests;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.appdeployer.command.CommandContext;
5+
import com.marklogic.mgmt.api.forest.ForestReplica;
6+
import org.junit.Assert;
7+
import org.junit.Test;
8+
9+
public class BuildForestReplicaTest extends Assert {
10+
11+
/**
12+
* Small unit test to verify that a ForestReplica is built correctly based on the AppConfig.ø
13+
*/
14+
@Test
15+
public void test() {
16+
AppConfig config = new AppConfig();
17+
config.setReplicaForestFastDataDirectory("/var/fast");
18+
config.setReplicaForestLargeDataDirectory("/var/large");
19+
config.setReplicaForestDataDirectory("/var/data");
20+
CommandContext context = new CommandContext(config, null, null);
21+
22+
ConfigureForestReplicasCommand command = new ConfigureForestReplicasCommand();
23+
ForestReplica replica = command.buildForestReplica("test-name", "host-1", config);
24+
assertEquals("test-name", replica.getReplicaName());
25+
assertEquals("host-1", replica.getHost());
26+
assertEquals("/var/data", replica.getDataDirectory());
27+
assertEquals("/var/fast", replica.getFastDataDirectory());
28+
assertEquals("/var/large", replica.getLargeDataDirectory());
29+
}
30+
}

src/test/java/com/marklogic/appdeployer/command/forests/ConfigureForestReplicasDebug.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
public class ConfigureForestReplicasDebug {
1414

1515
public static void main(String[] args) {
16-
final String host = args[0];
17-
final String password = args[1];
16+
final String host = "localhost"; //args[0];
17+
final String password = "admin"; //args[1];
1818

1919
ManageConfig config = new ManageConfig(host, 8002, "admin", password);
2020
ManageClient manageClient = new ManageClient(config);
2121
AppConfig appConfig = new AppConfig();
2222
appConfig.setDatabaseNamesAndReplicaCounts("testdb,1");
23+
appConfig.setReplicaForestDataDirectory("/var/opt/MarkLogic/Replica");
24+
appConfig.setReplicaForestLargeDataDirectory("/var/opt/MarkLogic/Large");
25+
appConfig.setReplicaForestFastDataDirectory("/var/opt/MarkLogic/Fast");
2326
CommandContext context = new CommandContext(appConfig, manageClient, null);
2427

2528
DeployDatabaseCommand ddc = new DeployDatabaseCommand();
@@ -33,7 +36,10 @@ public static void main(String[] args) {
3336
ddc.execute(context);
3437
cfrc.execute(context);
3538

36-
// Then delete the replicas, and then undeploy the database
39+
// Deploy again to make sure there are no errors
40+
cfrc.execute(context);
41+
42+
// Then delete the replicas, and then undeploy the database
3743
cfrc.undo(context);
3844
ddc.undo(context);
3945
}

0 commit comments

Comments
 (0)