Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HubAppDeployer no longer loses functionality in SimpleAppDeployer #1700

Merged
merged 1 commit into from Dec 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
@@ -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;
}
}