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

Commit 406d647

Browse files
authored
Merge pull request #178 from marklogic-community/issue-31-review
changes for deploying/un-deploying sub-databases
2 parents 90e682c + 5f15565 commit 406d647

File tree

12 files changed

+328
-2
lines changed

12 files changed

+328
-2
lines changed

src/main/java/com/marklogic/appdeployer/command/databases/DeployContentDatabasesCommand.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ public void undo(CommandContext context) {
7777
String json = payloadTokenReplacer.replaceTokens(payload, appConfig, false);
7878

7979
DatabaseManager dbMgr = newDatabaseManageForDeleting(context);
80+
81+
// remove subdatabases if they exist
82+
removeSubDatabases(dbMgr, context, dbMgr.getResourceId(json));
83+
8084
dbMgr.delete(json);
8185
if (appConfig.isTestPortSet()) {
8286
json = payloadTokenReplacer.replaceTokens(payload, appConfig, true);

src/main/java/com/marklogic/appdeployer/command/databases/DeployDatabaseCommand.java

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import com.marklogic.mgmt.resource.databases.DatabaseManager;
1212

1313
import java.io.File;
14+
import java.util.ArrayList;
15+
import java.util.List;
1416
import java.util.Map;
1517

1618
/**
@@ -62,6 +64,10 @@ public class DeployDatabaseCommand extends AbstractCommand implements UndoableCo
6264
private boolean createForestsOnEachHost = true;
6365

6466
private int undoSortOrder;
67+
68+
private boolean isSubDatabase = false;
69+
private String superDatabaseName;
70+
6571

6672
public DeployDatabaseCommand() {
6773
setExecuteSortOrder(SortOrderConstants.DEPLOY_OTHER_DATABASES);
@@ -82,30 +88,110 @@ public String toString() {
8288
public Integer getUndoSortOrder() {
8389
return undoSortOrder;
8490
}
91+
92+
public void setIsSubDatabase(boolean isSubDatabase){
93+
this.isSubDatabase = isSubDatabase;
94+
}
95+
96+
public boolean isSubDatabase() {
97+
return this.isSubDatabase;
98+
}
99+
100+
public void setSuperDatabaseName(String name){
101+
this.superDatabaseName = name;
102+
}
103+
public String getSuperDatabaseName() {
104+
return this.superDatabaseName;
105+
}
106+
85107

86108
@Override
87109
public void execute(CommandContext context) {
88110
String payload = buildPayload(context);
89111
if (payload != null) {
90112
DatabaseManager dbMgr = new DatabaseManager(context.getManageClient());
91113
SaveReceipt receipt = dbMgr.save(payload);
114+
115+
databaseName = receipt.getResourceId();
92116
if (shouldCreateForests(context, payload)) {
93117
buildDeployForestsCommand(payload, receipt, context).execute(context);
94118
} else {
95119
if (logger.isInfoEnabled()) {
96120
logger.info("Found custom forests for database, so not creating default forests");
97121
}
98122
}
123+
// subdatabases? create and attach
124+
if(!isSubDatabase()){
125+
this.addSubDatabases(dbMgr, context, receipt.getResourceId());
126+
}
127+
99128
}
100129
}
101130

102131
@Override
103132
public void undo(CommandContext context) {
104133
String payload = buildPayload(context);
105134
if (payload != null) {
106-
newDatabaseManageForDeleting(context).delete(payload);
135+
DatabaseManager dbMgr = newDatabaseManageForDeleting(context);
136+
// if this has subdatabases, detach/delete them first
137+
if(!isSubDatabase()){
138+
removeSubDatabases(dbMgr, context, dbMgr.getResourceId(payload));
139+
}
140+
dbMgr.delete(payload);
141+
}
142+
}
143+
144+
/**
145+
* Creates and attaches sub-databases to a the specified database, making it a super-database.
146+
* Note: Sub-databases are expected to have a configuration files in databases/subdatabases/<super-database-name>
147+
* @param dbMgr
148+
* @param context
149+
* @param superDatabaseName Name of the database the sub-databases are to be associated with
150+
*/
151+
protected void addSubDatabases(DatabaseManager dbMgr, CommandContext context, String superDatabaseName) {
152+
File subdbDir = new File(context.getAppConfig().getConfigDir().getDatabasesDir() + File.separator + "subdatabases" + File.separator + superDatabaseName);
153+
logger.info(format("Checking for Subdatabases in: %s for database: %s", subdbDir.getAbsolutePath(), superDatabaseName));
154+
if(subdbDir.exists()){
155+
List<String> subDbNames = new ArrayList<String>();
156+
for (File f : listFilesInDirectory(subdbDir)) {
157+
logger.info(format("Will process sub database for %s found in file: %s", superDatabaseName, f.getAbsolutePath()));
158+
DeployDatabaseCommand subDbCommand = new DeployDatabaseCommand();
159+
subDbCommand.setDatabaseFilename(f.getName());
160+
subDbCommand.setSuperDatabaseName(superDatabaseName);
161+
subDbCommand.setIsSubDatabase(true);
162+
subDbCommand.execute(context);
163+
subDbNames.add(subDbCommand.getDatabaseName());
164+
logger.info(format("Created subdatabase %s for database %s", subDbCommand.getDatabaseName(), superDatabaseName));
165+
}
166+
if(subDbNames.size() > 0){
167+
dbMgr.attachSubDatabases(superDatabaseName, subDbNames);
168+
}
169+
}
170+
}
171+
172+
/**
173+
* Detaches and deletes all sub-databases for the specified super-database
174+
* @param dbMgr
175+
* @param context
176+
* @param superDatabaseName
177+
*/
178+
protected void removeSubDatabases(DatabaseManager dbMgr, CommandContext context, String superDatabaseName){
179+
File subdbDir = new File(context.getAppConfig().getConfigDir().getDatabasesDir() + File.separator + "subdatabases" + File.separator + superDatabaseName);
180+
logger.info(format("Checking to see if %s has subdatabases that need to be removed. Looking in folder: %s", superDatabaseName, subdbDir.getAbsolutePath()));
181+
if(subdbDir.exists()){
182+
logger.info("Removing all subdatabases from database: " + superDatabaseName);
183+
dbMgr.detachSubDatabases(superDatabaseName);
184+
for (File f : listFilesInDirectory(subdbDir)) {
185+
DeployDatabaseCommand subDbCommand = new DeployDatabaseCommand();
186+
subDbCommand.setDatabaseFilename(f.getName());
187+
subDbCommand.setSuperDatabaseName(superDatabaseName);
188+
subDbCommand.setIsSubDatabase(true);
189+
subDbCommand.undo(context);
190+
191+
}
107192
}
108193
}
194+
109195

110196
/**
111197
* Configures the DatabaseManager in terms of how it deletes forests based on properties in the AppConfig instance
@@ -146,7 +232,13 @@ public String buildPayload(CommandContext context) {
146232
protected String getPayload(CommandContext context) {
147233
File f = null;
148234
if (databaseFilename != null) {
149-
f = new File(context.getAppConfig().getConfigDir().getDatabasesDir(), databaseFilename);
235+
if(isSubDatabase()){
236+
String subDbFileName =context.getAppConfig().getConfigDir().getDatabasesDir() + File.separator + "subdatabases" + File.separator + this.getSuperDatabaseName() + File.separator + databaseFilename;
237+
logger.info("!!!! getting paylod for: " + subDbFileName);
238+
f = new File(subDbFileName);
239+
}else {
240+
f = new File(context.getAppConfig().getConfigDir().getDatabasesDir(), databaseFilename);
241+
}
150242
}
151243
if (f != null && f.exists()) {
152244
return copyFileToString(f);

src/main/java/com/marklogic/mgmt/resource/databases/DatabaseManager.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,44 @@ private void invokeOperation(String databaseIdOrName, String operation) {
5555
getManageClient().postJson(path, format("{\"operation\":\"%s\"}", operation));
5656
logger.info(format("Finished invoking operation %s on database %s", operation, databaseIdOrName));
5757
}
58+
59+
public String getResourceId(String payload){
60+
return super.getResourceId(payload);
61+
}
62+
63+
/**
64+
* Detaches or disassociates any sub-databases from this database
65+
* @param databaseIdOrName
66+
*/
67+
public void detachSubDatabases(String databaseIdOrName){
68+
logger.info("Detaching sub-databases from database: " + databaseIdOrName);
69+
save(format("{\"database-name\":\"%s\", \"subdatabase\": []}", databaseIdOrName));
70+
logger.info("Finished detaching sub-databases from database: " + databaseIdOrName);
71+
}
72+
73+
/**
74+
* Attaches/associates the specified databases with this database, making it a super-database.
75+
* Note: that the databases listed in subDbNames must have already been created.
76+
*
77+
* @param databaseIdOrName
78+
* @param subDbNames
79+
*/
80+
public void attachSubDatabases(String databaseIdOrName, List<String> subDbNames){
81+
String payload = format("{\"database-name\":\"%s\", \"subdatabase\": [", databaseIdOrName);
82+
for(int index = 0; index < subDbNames.size(); index++){
83+
if(index > 0){ payload += ","; }
84+
payload += format("{\"database-name\":\"%s\"}", subDbNames.get(index));
85+
}
86+
payload += "]}";
87+
logger.info("Attaching sub-databases to database: " + databaseIdOrName + ", using configured payload: " + payload);
88+
save(payload);
89+
logger.info("Finished attaching sub-databases to database: " + databaseIdOrName);
90+
91+
}
92+
93+
public List<String> getSubDatabases(String databaseNameOrId) {
94+
return getPropertiesAsXml(databaseNameOrId).getElementValues("/node()/m:subdatabases/m:subdatabase/m:database-name");
95+
}
5896

5997
public void deleteByName(String databaseName) {
6098
String json = format("{\"database-name\":\"%s\"}", databaseName);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.marklogic.appdeployer.command.databases;
2+
3+
import java.io.File;
4+
import java.util.List;
5+
6+
import org.junit.Test;
7+
8+
import com.marklogic.appdeployer.AbstractAppDeployerTest;
9+
import com.marklogic.appdeployer.ConfigDir;
10+
import com.marklogic.appdeployer.command.restapis.DeployRestApiServersCommand;
11+
import com.marklogic.mgmt.resource.databases.DatabaseManager;
12+
13+
public class DeployDatabasesAndSubDatabasesTest extends AbstractAppDeployerTest{
14+
@Test
15+
public void test() {
16+
ConfigDir configDir = appConfig.getConfigDir();
17+
configDir.setBaseDir(new File("src/test/resources/sample-app/subdatabases"));
18+
19+
initializeAppDeployer(new DeployRestApiServersCommand(), new DeployContentDatabasesCommand(2),
20+
new DeployTriggersDatabaseCommand(), new DeploySchemasDatabaseCommand(),
21+
new DeployOtherDatabasesCommand());
22+
23+
DatabaseManager dbMgr = new DatabaseManager(manageClient);
24+
25+
String[] dbNames = new String[] { "sample-app-content", "sample-app-triggers", "sample-app-schemas",
26+
"mysuperdb", "mysuperdb-subdb01", "mysuperdb-subdb02", "sample-app-content-subdb01", "sample-app-content-subdb01" };
27+
try {
28+
appDeployer.deploy(appConfig);
29+
30+
for (String name : dbNames) {
31+
assertTrue("Expected to find database: " + name, dbMgr.exists(name));
32+
}
33+
34+
// check that subdatabases are associated
35+
List<String> subDatabases = dbMgr.getSubDatabases("mysuperdb");
36+
assertTrue("Expected to find subdatabase of 'mysuperdb-subdb01'", subDatabases.contains("mysuperdb-subdb01"));
37+
assertTrue("Expected to find subdatabase of 'mysuperdb-subdb02'", subDatabases.contains("mysuperdb-subdb02"));
38+
39+
subDatabases = dbMgr.getSubDatabases("sample-app-content");
40+
assertTrue("Expected to find subdatabase of 'sample-app-content-subdb01'", subDatabases.contains("sample-app-content-subdb01"));
41+
assertTrue("Expected to find subdatabase of 'sample-app-content-subdb02'", subDatabases.contains("sample-app-content-subdb02"));
42+
43+
44+
} finally {
45+
46+
undeploySampleApp();
47+
48+
for (String name : dbNames) {
49+
assertFalse("Expected to not find database: " + name, dbMgr.exists(name));
50+
}
51+
52+
53+
}
54+
}
55+
56+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"database-name": "%%DATABASE%%",
3+
"triggers-database": "%%TRIGGERS_DATABASE%%",
4+
"schema-database": "%%SCHEMAS_DATABASE%%",
5+
"range-element-index" : [
6+
{
7+
"invalid-values" : "reject",
8+
"collation" : "http://marklogic.com/collation/",
9+
"localname" : "FirstName",
10+
"namespace-uri" : "http://person",
11+
"range-value-positions" : false,
12+
"scalar-type" : "string"
13+
},
14+
{
15+
"invalid-values" : "reject",
16+
"collation" : "",
17+
"localname" : "BirthDate",
18+
"namespace-uri" : "http://person",
19+
"range-value-positions" : false,
20+
"scalar-type" : "dateTime"
21+
}
22+
]
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"database-name": "mysuperdb",
3+
"triggers-database": "%%TRIGGERS_DATABASE%%",
4+
"schema-database": "%%SCHEMAS_DATABASE%%",
5+
"range-element-index" : [
6+
{
7+
"invalid-values" : "reject",
8+
"collation" : "http://marklogic.com/collation/",
9+
"localname" : "FirstName",
10+
"namespace-uri" : "http://person",
11+
"range-value-positions" : false,
12+
"scalar-type" : "string"
13+
},
14+
{
15+
"invalid-values" : "reject",
16+
"collation" : "",
17+
"localname" : "BirthDate",
18+
"namespace-uri" : "http://person",
19+
"range-value-positions" : false,
20+
"scalar-type" : "dateTime"
21+
}
22+
]
23+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"database-name": "%%SCHEMAS_DATABASE%%"
3+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"database-name": "mysuperdb-subdb01",
3+
"range-element-index" : [
4+
{
5+
"invalid-values" : "reject",
6+
"collation" : "http://marklogic.com/collation/",
7+
"localname" : "FirstName",
8+
"namespace-uri" : "http://person",
9+
"range-value-positions" : false,
10+
"scalar-type" : "string"
11+
},
12+
{
13+
"invalid-values" : "reject",
14+
"collation" : "",
15+
"localname" : "BirthDate",
16+
"namespace-uri" : "http://person",
17+
"range-value-positions" : false,
18+
"scalar-type" : "dateTime"
19+
}
20+
]
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"database-name": "mysuperdb-subdb02",
3+
"range-element-index" : [
4+
{
5+
"invalid-values" : "reject",
6+
"collation" : "http://marklogic.com/collation/",
7+
"localname" : "FirstName",
8+
"namespace-uri" : "http://person",
9+
"range-value-positions" : false,
10+
"scalar-type" : "string"
11+
},
12+
{
13+
"invalid-values" : "reject",
14+
"collation" : "",
15+
"localname" : "BirthDate",
16+
"namespace-uri" : "http://person",
17+
"range-value-positions" : false,
18+
"scalar-type" : "dateTime"
19+
}
20+
]
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"database-name": "sample-app-content-subdb01",
3+
"range-element-index" : [
4+
{
5+
"invalid-values" : "reject",
6+
"collation" : "http://marklogic.com/collation/",
7+
"localname" : "FirstName",
8+
"namespace-uri" : "http://person",
9+
"range-value-positions" : false,
10+
"scalar-type" : "string"
11+
},
12+
{
13+
"invalid-values" : "reject",
14+
"collation" : "",
15+
"localname" : "BirthDate",
16+
"namespace-uri" : "http://person",
17+
"range-value-positions" : false,
18+
"scalar-type" : "dateTime"
19+
}
20+
]
21+
}

0 commit comments

Comments
 (0)