Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/main/java/com/marklogic/appdeployer/mgmt/AdminConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.marklogic.appdeployer.mgmt;

import com.marklogic.appdeployer.util.RestConfig;

/**
* Defines the configuration data for talking to the Admin REST API.
*/
public class AdminConfig extends RestConfig {

public AdminConfig() {
super("localhost", 8001, "admin", "admin");
}

public AdminConfig(String host, String password) {
super(host, 8001, "admin", password);
}

public AdminConfig(String host, int port, String username, String password) {
super(host, port, username, password);
}

}
90 changes: 59 additions & 31 deletions src/main/java/com/marklogic/appdeployer/mgmt/ConfigManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,8 @@
import java.io.File;
import java.io.IOException;

import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.util.ClassUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.marklogic.appdeployer.AppConfig;
Expand All @@ -26,7 +19,8 @@
public class ConfigManager extends LoggingObject {

private ManageClient client;
private AppServicesConfig appServicesConfig;
private AdminConfig adminConfig;
private int waitForRestartCheckInterval = 500;

public ConfigManager(ManageClient client) {
this.client = client;
Expand Down Expand Up @@ -74,36 +68,58 @@ protected String replaceTestRestApiTokens(String input, AppConfig config) {
return input;
}

public void uninstallApp(AppConfig config) {
if (appServicesConfig == null) {
throw new IllegalStateException("Cannot uninstall an app without an instance of AppServicesConfig set");
public void deleteRestApiAndWaitForRestart(AppConfig config, boolean includeModules, boolean includeContent) {
String timestamp = getLastRestartTimestamp();
logger.info("About to delete REST API, will then wait for MarkLogic to restart");
deleteRestApi(config, includeModules, includeContent);
waitForRestart(timestamp);
}

public void deleteRestApi(AppConfig config, boolean includeModules, boolean includeContent) {
String path = client.getBaseUrl() + "/v1/rest-apis/" + config.getName() + "?";
if (includeModules) {
path += "include=modules&";
}
String xquery = loadStringFromClassPath("uninstall-app.xqy");
xquery = xquery.replace("%%APP_NAME%%", config.getName());
if (includeContent) {
path += "include=content";
}
logger.info("Deleting app, path: " + path);
client.getRestTemplate().exchange(path, HttpMethod.DELETE, null, String.class);
logger.info("Finished deleting app");
}

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("xquery", xquery);
public void waitForRestart(String lastRestartTimestamp) {
logger.info("Waiting for MarkLogic to restart, last restart timestamp: " + lastRestartTimestamp);
logger.info("Ignore any HTTP client logging about socket exceptions and retries, those are expected while waiting for MarkLogic to restart");
while (true) {
sleepUntilNextRestartCheck();
String restart = getLastRestartTimestamp();
if (restart != null && !restart.equals(lastRestartTimestamp)) {
logger.info(String
.format("MarkLogic has successfully restarted; new restart timestamp [%s] is greater than last restart timestamp [%s]",
restart, lastRestartTimestamp));
break;
}
}
}

logger.info("Uninstalling app with name: " + config.getName());
protected void sleepUntilNextRestartCheck() {
try {
RestTemplate rt = RestTemplateUtil.newRestTemplate(appServicesConfig);
rt.exchange("http://localhost:8000/v1/eval", HttpMethod.POST,
new HttpEntity<MultiValueMap<String, String>>(map, headers), String.class);
Thread.sleep(getWaitForRestartCheckInterval());
} catch (Exception e) {
logger.warn("Could not uninstall app; it may not be installed yet? Cause: " + e.getMessage());
// ignore
}
}

protected String loadStringFromClassPath(String path) {
path = ClassUtils.addResourcePathToPackagePath(getClass(), path);
try {
return new String(FileCopyUtils.copyToByteArray(new ClassPathResource(path).getInputStream()));
} catch (IOException ie) {
throw new RuntimeException("Unable to load string from classpath resource at: " + path + "; cause: "
+ ie.getMessage(), ie);
/**
* TODO May want to extract this into an AdminManager that depends on AdminConfig.
*/
public String getLastRestartTimestamp() {
if (adminConfig == null) {
throw new IllegalStateException("Cannot access admin app, no admin config provided");
}
RestTemplate t = RestTemplateUtil.newRestTemplate(adminConfig);
return t.getForEntity(adminConfig.getBaseUrl() + "/admin/v1/timestamp", String.class).getBody();
}

protected String copyFileToString(File f) {
Expand All @@ -115,7 +131,19 @@ protected String copyFileToString(File f) {
}
}

public void setAppServicesConfig(AppServicesConfig appServicesConfig) {
this.appServicesConfig = appServicesConfig;
public AdminConfig getAdminConfig() {
return adminConfig;
}

public void setAdminConfig(AdminConfig adminConfig) {
this.adminConfig = adminConfig;
}

public int getWaitForRestartCheckInterval() {
return waitForRestartCheckInterval;
}

public void setWaitForRestartCheckInterval(int waitForRestartCheckInterval) {
this.waitForRestartCheckInterval = waitForRestartCheckInterval;
}
}
142 changes: 0 additions & 142 deletions src/main/java/com/marklogic/appdeployer/mgmt/uninstall-app.xqy

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.marklogic.appdeployer.mgmt;

import java.io.File;

import org.junit.Assert;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.marklogic.appdeployer.AppConfig;

/**
* Base class for tests that run against the new management API in ML8. Main purpose is to provide convenience methods
* for quickly creating and deleting a sample application.
*/
public abstract class AbstractMgmtTest extends Assert {

public final static String SAMPLE_APP_NAME = "sample-app";

protected final Logger logger = LoggerFactory.getLogger(getClass());

protected ManageConfig manageConfig;
protected ManageClient manageClient;

protected ConfigDir configDir;
protected ConfigManager configMgr;

protected AppConfig appConfig;

@Before
public void initialize() {
manageClient = new ManageClient(new ManageConfig());
configDir = new ConfigDir(new File("src/test/resources/sample-app/src/main/ml-config"));
configMgr = new ConfigManager(manageClient);
initializeAppConfig();
}

protected void createSampleApp() {
configMgr.createRestApi(configDir, appConfig);
}

protected void initializeAppConfig() {
appConfig = new AppConfig();
appConfig.setName("sample-app");
appConfig.setRestPort(8540);
}

protected void deleteSampleApp() {
configMgr.deleteRestApiAndWaitForRestart(appConfig, true, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.marklogic.appdeployer.mgmt;

import org.junit.Test;

import com.marklogic.appdeployer.mgmt.services.ServiceManager;

/**
* This test ensures that the convenience methods for creating and deleting a sample application work properly, and thus
* they can be used in other tests that depend on having an app in place.
*/
public class DeleteRestApiTest extends AbstractMgmtTest {

@Test
public void createAndDelete() {
ServiceManager mgr = new ServiceManager(manageClient);

createSampleApp();
assertTrue("The REST API server should exist", mgr.restApiServerExists(SAMPLE_APP_NAME));

configMgr.setAdminConfig(new AdminConfig());
deleteSampleApp();
assertFalse("The REST API server should have been deleted", mgr.restApiServerExists(SAMPLE_APP_NAME));
}
}
Loading