Skip to content

Commit

Permalink
HubAppDeployer no longer loses functionality in SimpleAppDeployer (#1700
Browse files Browse the repository at this point in the history
)

HubAppDeployer now extends SimpleAppDeployer in a way that it doesn't lose any functionality.
  • Loading branch information
rjrudin authored and aebadirad committed Dec 20, 2018
1 parent fc81d08 commit a26b42a
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@
import com.marklogic.mgmt.ManageClient;
import com.marklogic.mgmt.admin.AdminManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
* Extends ml-app-deployer's SimpleAppDeployer to provide progress reporting.
*/
public class HubAppDeployer extends SimpleAppDeployer {

private ManageClient manageClient;
Expand All @@ -40,6 +38,9 @@ public class HubAppDeployer extends SimpleAppDeployer {
// this is for the telemetry hook to use mlUsername/mlPassword
private DatabaseClient databaseClient;

// Keeps track of completion percentage
private int completed = 0;

public HubAppDeployer(ManageClient manageClient, AdminManager adminManager, HubDeployStatusListener listener, DatabaseClient databaseClient) {
super(manageClient, adminManager);
this.manageClient = manageClient;
Expand All @@ -50,94 +51,54 @@ public HubAppDeployer(ManageClient manageClient, AdminManager adminManager, HubD

@Override
public void deploy(AppConfig appConfig) {
logger.info(format("Deploying app %s with config dir of: %s\n", appConfig.getName(), appConfig.getFirstConfigDir()
.getBaseDir().getAbsolutePath()));

List<Command> commands = getCommands();
Collections.sort(commands, new Comparator<Command>() {
@Override
public int compare(Command o1, Command o2) {
return o1.getExecuteSortOrder().compareTo(o2.getExecuteSortOrder());
}

@Override
public boolean equals(Object obj) {
return this.equals(obj);
}
});
this.completed = 0;

CommandContext context = new CommandContext(appConfig, manageClient, adminManager);

int count = commands.size();
int completed = 0;
onStatusChange(0, "Installing...");
for (Command command : commands) {
String name = command.getClass().getName();
logger.info(format("Executing command [%s] with sort order [%d]", name, command.getExecuteSortOrder()));
float percent = ((float)completed / (float)count) * 100;
onStatusChange((int)percent, format("[Step %d of %d] %s", completed + 1, count, name));
command.execute(context);
logger.info(format("Finished executing command [%s]\n", name));
completed++;
}
super.deploy(appConfig);
onStatusChange(100, "Installation Complete");

//Below is telemetry metric code for tracking successful dhf installs
//TODO: when more uses of telemetry are defined, change this to a more e-node based method
ServerEvaluationCall eval = databaseClient.newServerEval();
String query = "xdmp:feature-metric-increment(xdmp:feature-metric-register(\"datahub.core.install.count\"))";
try {
eval.xquery(query).eval().close();
}
catch(FailedRequestException e) {
logger.error("Failed to increment feature metric telemetry count: " + query, e);
e.printStackTrace();
if (databaseClient != null) {
//Below is telemetry metric code for tracking successful dhf installs
//TODO: when more uses of telemetry are defined, change this to a more e-node based method
ServerEvaluationCall eval = databaseClient.newServerEval();
String query = "xdmp:feature-metric-increment(xdmp:feature-metric-register(\"datahub.core.install.count\"))";
try {
eval.xquery(query).eval().close();
} catch (FailedRequestException e) {
logger.error("Failed to increment feature metric telemetry count: " + query, e);
e.printStackTrace();
}
}
logger.info(format("Deployed app %s", appConfig.getName()));
}

@Override
public void undeploy(AppConfig appConfig) {
logger.info(format("Undeploying app %s with config dir: %s\n", appConfig.getName(), appConfig.getFirstConfigDir()
.getBaseDir().getAbsolutePath()));

List<Command> commands = getCommands();

List<UndoableCommand> undoableCommands = new ArrayList<>();
for (Command command : commands) {
if (command instanceof UndoableCommand) {
undoableCommands.add((UndoableCommand) command);
}
}

Collections.sort(undoableCommands, new Comparator<UndoableCommand>() {
@Override
public int compare(UndoableCommand o1, UndoableCommand o2) {
return o1.getUndoSortOrder().compareTo(o2.getUndoSortOrder());
}
protected void executeCommand(Command command, CommandContext context) {
reportStatus(command);
super.executeCommand(command, context);
completed++;
}

@Override
public boolean equals(Object obj) {
return this.equals(obj);
}
});
@Override
public void undeploy(AppConfig appConfig) {
this.completed = 0;

int count = undoableCommands.size();
int completed = 0;
onStatusChange(0, "Uninstalling...");

for (UndoableCommand command : undoableCommands) {
String name = command.getClass().getName();
logger.info(format("Undoing command [%s] with sort order [%d]", name, command.getUndoSortOrder()));
float percent = ((float)completed / (float)count) * 100;
onStatusChange((int)percent, format("[Step %d of %d] %s", completed + 1, count, name));
command.undo(new CommandContext(appConfig, manageClient, adminManager));
logger.info(format("Finished undoing command [%s]\n", name));
completed++;
}
super.undeploy(appConfig);
onStatusChange(100, "Installation Complete");
}

@Override
protected void undoCommand(UndoableCommand command, CommandContext context) {
reportStatus(command);
super.undoCommand(command, context);
completed++;
}

logger.info(format("Undeployed app %s", appConfig.getName()));
protected void reportStatus(Command command) {
int count = getCommands().size();
float percent = ((float) completed / (float) count) * 100;
String name = command.getClass().getName();
onStatusChange((int) percent, format("[Step %d of %d] %s", completed + 1, count, name));
}

private void onStatusChange(int percentComplete, String message) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.marklogic.hub.deploy;

import com.marklogic.appdeployer.AppConfig;
import com.marklogic.appdeployer.command.Command;
import com.marklogic.appdeployer.command.CommandContext;
import com.marklogic.hub.deploy.util.HubDeployStatusListener;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

public class HubAppDeployerTest {

@Test
public void test() {
List<String> messages = new ArrayList<>();

List<Command> commands = new ArrayList<>();
commands.add(new TestCommand(20, messages));
commands.add(new TestCommand(30, messages));
commands.add(new TestCommand(10, messages));

TestListener testListener = new TestListener();

HubAppDeployer appDeployer = new HubAppDeployer(null, null, testListener, null);
appDeployer.setCommands(commands);
appDeployer.deploy(new AppConfig());

// Verify commands were executed in correct order
assertEquals("My sort order: 10", messages.get(0));
assertEquals("My sort order: 20", messages.get(1));
assertEquals("My sort order: 30", messages.get(2));

// Verify correct status messages were passed to our listener
System.out.println(testListener.getMessages());
assertEquals("0:Installing...", testListener.getMessages().get(0));
assertEquals("0:[Step 1 of 3] com.marklogic.hub.deploy.TestCommand", testListener.getMessages().get(1));
assertEquals("33:[Step 2 of 3] com.marklogic.hub.deploy.TestCommand", testListener.getMessages().get(2));
assertEquals("66:[Step 3 of 3] com.marklogic.hub.deploy.TestCommand", testListener.getMessages().get(3));
assertEquals("100:Installation Complete", testListener.getMessages().get(4));
}
}

class TestCommand implements Command {

private int sortOrder;
private List<String> messages;

public TestCommand(int sortOrder, List<String> messages) {
this.sortOrder = sortOrder;
this.messages = messages;
}

@Override
public void execute(CommandContext context) {
messages.add("My sort order: " + sortOrder);
}

@Override
public Integer getExecuteSortOrder() {
return sortOrder;
}
}

class TestListener implements HubDeployStatusListener {

private List<String> messages = new ArrayList<>();

@Override
public void onStatusChange(int percentComplete, String message) {
messages.add(percentComplete + ":" + message);
}

@Override
public void onError() {

}

public List<String> getMessages() {
return messages;
}
}

0 comments on commit a26b42a

Please sign in to comment.