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

Commit

Permalink
#106 Can now create custom forests
Browse files Browse the repository at this point in the history
  • Loading branch information
rjrudin committed Jul 19, 2016
1 parent dfb31d7 commit ee8bb18
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 42 deletions.
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# http://editorconfig.org
root = true

[*]
indent_style = tab
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.java]
indent_size = 4
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public Integer getExecuteSortOrder() {
/**
* Convenience method for setting the names of files to ignore when reading resources from a directory. Will
* preserve any filenames already being ignored on the underlying FilenameFilter.
*
*
* @param filenames
*/
public void setFilenamesToIgnore(String... filenames) {
Expand All @@ -59,7 +59,7 @@ public void setFilenamesToIgnore(String... filenames) {

/**
* Simplifies reading the contents of a File into a String.
*
*
* @param f
* @return
*/
Expand All @@ -73,17 +73,29 @@ protected String copyFileToString(File f) {
}
}

/**
* Convenience function for reading the file into a string and replace tokens as well. Assumes this is not
* for a test-only resource.
*
* @param f
* @param context
* @return
*/
protected String copyFileToString(File f, CommandContext context) {
String str = copyFileToString(f);
return str != null ? tokenReplacer.replaceTokens(str, context.getAppConfig(), false) : str;
}

/**
* Provides a basic implementation for saving a resource defined in a File, including replacing tokens.
*
*
* @param mgr
* @param context
* @param f
* @return
*/
protected SaveReceipt saveResource(ResourceManager mgr, CommandContext context, File f) {
String payload = copyFileToString(f);
payload = tokenReplacer.replaceTokens(payload, context.getAppConfig(), false);
String payload = copyFileToString(f, context);
SaveReceipt receipt = mgr.save(payload);
if (storeResourceIdsAsCustomTokens) {
storeTokenForResourceId(receipt, context);
Expand All @@ -95,7 +107,7 @@ protected SaveReceipt saveResource(ResourceManager mgr, CommandContext context,
* Any resource that may be referenced by its ID by another resource will most likely need its ID stored as a custom
* token so that it can be referenced by the other resource. To enable this, the subclass should set
* storeResourceIdAsCustomToken to true.
*
*
* @param receipt
* @param context
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void execute(CommandContext context) {

/**
* Subclasses can override this to add functionality after a resource has been saved.
*
*
* @param mgr
* @param context
* @param resourceFile
Expand Down Expand Up @@ -77,13 +77,13 @@ public void undo(CommandContext context) {
* delete the resource. This has been necessary when deleting two app servers in a row - for some reason, the 2nd
* delete will intermittently fail with a connection reset error, but the app server is in fact deleted
* successfully.
*
*
* @param mgr
* @param context
* @param f
*/
protected void deleteResource(final ResourceManager mgr, CommandContext context, File f) {
final String payload = tokenReplacer.replaceTokens(copyFileToString(f), context.getAppConfig(), false);
final String payload = copyFileToString(f, context);
try {
if (restartAfterDelete) {
context.getAdminManager().invokeActionRequiringRestart(new ActionRequiringRestart() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected void deployRulesInDirectory(File dir, CommandContext context) {
* parse its contents.
*/
for (File f : listFilesInDirectory(dir)) {
String payload = copyFileToString(f);
String payload = copyFileToString(f, context);
String actionName = payloadParser.getPayloadFieldValue(payload, "action-name");
AlertRuleManager mgr = new AlertRuleManager(context.getManageClient(), dbName, configUri, actionName);
saveResource(mgr, context, f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ public void execute(CommandContext context) {
if (dir.exists()) {
AbstractCpfResourceManager mgr = getResourceManager(context);
for (File f : listFilesInDirectory(dir)) {
String payload = copyFileToString(f);
payload = tokenReplacer.replaceTokens(payload, config, false);
String payload = copyFileToString(f, context);
mgr.save(config.getTriggersDatabaseName(), payload);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* Command for configuring - i.e. creating and setting - replica forests for existing databases and/or primary forests.
* It's normally easier to just specify the databases that you want to configure forest replicas for, but this command
* does provide the ability to configure replicas for specific forests.
*
*
* Very useful for the out-of-the-box forests such as Security, Schemas, App-Services, and Meters, which normally need
* replicas for failover in a cluster.
*/
Expand All @@ -38,7 +38,7 @@ public ConfigureForestReplicasCommand() {
/**
* Allows for the map of database names and counts to be configured as a comma-delimited string of the form:
* "dbName,replicaCount,dbName,replicaCount,etc".
*
*
* @param str
*/
public void setDatabaseNamesAndReplicaCountsAsString(String str) {
Expand Down Expand Up @@ -96,7 +96,7 @@ public void undo(CommandContext context) {
if (str != null) {
setDatabaseNamesAndReplicaCountsAsString(str);
}

DatabaseManager dbMgr = new DatabaseManager(context.getManageClient());
ForestManager forestMgr = new ForestManager(context.getManageClient());

Expand Down Expand Up @@ -132,7 +132,7 @@ protected void deleteReplicas(String forestName, ForestManager forestMgr) {
* For the given database, find all of its primary forests. Then for each primary forest, just call
* configureReplicaForests? And that should be smart enough to say - if the primary forest already has replicas,
* then don't do anything.
*
*
* @param databaseName
* @param replicaCount
* @param hostIds
Expand All @@ -151,7 +151,7 @@ protected void configureDatabaseReplicaForests(String databaseName, int replicaC
/**
* Creates forests as needed (they may already exists) and then sets those forests as the replicas for the given
* primaryForestName.
*
*
* @param forestIdOrName
* @param replicaCount
* @param hostIds
Expand All @@ -178,7 +178,7 @@ protected void configureReplicaForests(String forestIdOrName, int replicaCount,
if (!hostId.equals(primaryForestHostId)) {
for (int i = 0; i < replicaCount; i++) {
String name = forestIdOrName + "-" + resourceCounter;
forestMgr.createForestWithName(name, hostId);
forestMgr.createJsonForestWithName(name, hostId);
replicaNamesAndHostIds.put(name, hostId);
resourceCounter++;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.marklogic.appdeployer.command.forests;

import com.marklogic.appdeployer.command.AbstractCommand;
import com.marklogic.appdeployer.command.CommandContext;
import com.marklogic.appdeployer.command.SortOrderConstants;
import com.marklogic.mgmt.forests.ForestManager;

import java.io.File;

/**
* Use this command when you want precise control over the forests that are created for a database. It processes
* each directory under ml-config/forests (the name of the directory does not matter, but it makes sense to name
* it after the database that the forests belong to), and each file in a directory can have a single forest object
* or an array of forest objects.
*/
public class DeployCustomForestsCommand extends AbstractCommand {

public DeployCustomForestsCommand() {
setExecuteSortOrder(SortOrderConstants.DEPLOY_FORESTS);
}

@Override
public void execute(CommandContext context) {
File dir = new File(context.getAppConfig().getConfigDir().getBaseDir(), "forests");
for (File f : dir.listFiles()) {
if (f.isDirectory()) {
processDirectory(f, context);
}
}
}

protected void processDirectory(File dir, CommandContext context) {
ForestManager mgr = new ForestManager(context.getManageClient());
for (File f : listFilesInDirectory(dir)) {
String payload = copyFileToString(f, context);
mgr.saveJsonForests(payload);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
import com.marklogic.mgmt.hosts.HostManager;

/**
* This command is for a simple use case where all the forests created for a database have the same structure,
* but possibly exist on different forests. For more precise control over how forests are created, please see
* DeployCustomForestsCommand.
*
* Doesn't yet support deleting forests - currently assumed that this will be done by deleting a database.
*/
public class DeployForestsCommand extends AbstractCommand {
Expand Down Expand Up @@ -148,4 +152,4 @@ public boolean isCreateForestsOnEachHost() {
public void setCreateForestsOnEachHost(boolean createForestsOnEachHost) {
this.createForestsOnEachHost = createForestsOnEachHost;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void execute(CommandContext context) {
if (logger.isInfoEnabled()) {
logger.info("Creating certificate authority from file: " + f.getAbsolutePath());
}
String payload = copyFileToString(f);
String payload = copyFileToString(f, context);
ResponseEntity<String> response = mgr.create(payload);
if (logger.isInfoEnabled()) {
logger.info("Created certificate authority, location: " + response.getHeaders().getLocation());
Expand Down
32 changes: 25 additions & 7 deletions src/main/java/com/marklogic/mgmt/forests/ForestManager.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.marklogic.mgmt.forests;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.marklogic.mgmt.AbstractResourceManager;
import com.marklogic.mgmt.ManageClient;
import com.marklogic.rest.util.Fragment;
Expand All @@ -20,15 +22,14 @@ public class ForestManager extends AbstractResourceManager {

public ForestManager(ManageClient client) {
super(client);
setUpdateAllowed(false);
}

public void createForestWithName(String name, String host) {
public void createJsonForestWithName(String name, String host) {
if (forestExists(name)) {
logger.info(format("Forest already exists with name, so not creating: %s", name));
} else {
logger.info(format("Creating forest %s on host %s", name, host));
createForest(format("{\"forest-name\":\"%s\", \"host\":\"%s\"}", name, host));
createJsonForest(format("{\"forest-name\":\"%s\", \"host\":\"%s\"}", name, host));
logger.info(format("Created forest %s on host %s", name, host));
}
}
Expand All @@ -43,7 +44,24 @@ public void delete(String nameOrId, String level) {
}
}

public void createForest(String json) {
/**
* Supports either an array of JSON objects or a single JSON object.
*
* @param json
*/
public void saveJsonForests(String json) {
JsonNode node = super.payloadParser.parseJson(json);
if (node.isArray()) {
Iterator<JsonNode> iter = node.iterator();
while (iter.hasNext()) {
save(iter.next().toString());
}
} else {
save(json);
}
}

public void createJsonForest(String json) {
getManageClient().postJson("/manage/v2/forests", json);
}

Expand Down Expand Up @@ -103,7 +121,7 @@ public void setReplicas(String forestIdOrName, Map<String, String> replicaNamesA
/**
* Convenience method for detaching a forest from any replicas it has; this is often used before deleting those
* replicas
*
*
* @param forestIdOrName
*/
public void setReplicasToNone(String forestIdOrName) {
Expand All @@ -112,7 +130,7 @@ public void setReplicasToNone(String forestIdOrName) {

/**
* Returns a list of IDs for each replica forest for the given forest ID or name.
*
*
* @param forestIdOrName
* @return
*/
Expand All @@ -124,7 +142,7 @@ public List<String> getReplicaIds(String forestIdOrName) {

/**
* Deletes (with a level of "full") all replicas for the given forest.
*
*
* @param forestIdOrName
*/
public void deleteReplicas(String forestIdOrName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ public abstract class AbstractAppDeployerTest extends AbstractMgmtTest {
protected final static Integer SAMPLE_APP_REST_PORT = 8540;
protected final static Integer SAMPLE_APP_TEST_REST_PORT = 8541;

@Autowired
private ManageConfig manageConfig;

private ConfigurableApplicationContext appManagerContext;

// Intended to be used by subclasses
protected AppDeployer appDeployer;
protected AppConfig appConfig;
Expand Down Expand Up @@ -60,24 +55,17 @@ protected void initializeAppDeployer() {

/**
* Initialize an AppDeployer with the given set of commands. Avoids having to create a Spring configuration.
*
*
* @param commands
*/
protected void initializeAppDeployer(Command... commands) {
appDeployer = new SimpleAppDeployer(manageClient, adminManager, commands);
}

@After
public void closeAppContext() {
if (appManagerContext != null) {
appManagerContext.close();
}
}

protected void deploySampleApp() {
appDeployer.deploy(appConfig);
}

protected void undeploySampleApp() {
try {
appDeployer.undeploy(appConfig);
Expand All @@ -102,7 +90,7 @@ protected LoadModulesCommand buildLoadModulesCommand() {
command.setModulesLoader(loader);
return command;
}

protected void setConfigBaseDir(String path) {
appConfig.getConfigDir().setBaseDir(new File("src/test/resources/" + path));
}
Expand Down
Loading

0 comments on commit ee8bb18

Please sign in to comment.