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

Commit 5aa8478

Browse files
committed
#336 Host names can now be set as tokens before a deployment starts
1 parent 4d4d6b4 commit 5aa8478

File tree

8 files changed

+237
-90
lines changed

8 files changed

+237
-90
lines changed

src/main/java/com/marklogic/appdeployer/AppConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public class AppConfig {
7373
private boolean deployForestsWithCma = false;
7474
private boolean deployPrivilegesWithCma = false;
7575

76+
private boolean addHostNameTokens = false;
77+
7678
// Used to construct DatabaseClient instances based on inputs defined in this class
7779
private ConfiguredDatabaseClientFactory configuredDatabaseClientFactory = new DefaultConfiguredDatabaseClientFactory();
7880

@@ -1295,4 +1297,12 @@ public boolean isTdeValidationEnabled() {
12951297
public void setTdeValidationEnabled(boolean tdeValidationEnabled) {
12961298
this.tdeValidationEnabled = tdeValidationEnabled;
12971299
}
1300+
1301+
public boolean isAddHostNameTokens() {
1302+
return addHostNameTokens;
1303+
}
1304+
1305+
public void setAddHostNameTokens(boolean addHostNameTokens) {
1306+
this.addHostNameTokens = addHostNameTokens;
1307+
}
12981308
}

src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ public void initialize() {
6565
config.setDeployPrivilegesWithCma(Boolean.parseBoolean(prop));
6666
});
6767

68+
propertyConsumerMap.put("mlAddHostNameTokens", (config, prop) -> {
69+
logger.info("Add host names to the custom tokens map: " + prop);
70+
config.setAddHostNameTokens(Boolean.parseBoolean(prop));
71+
});
72+
6873
/**
6974
* The application name is used as a prefix for default names for a variety of resources, such as REST API servers
7075
* and databases.

src/main/java/com/marklogic/appdeployer/impl/AbstractAppDeployer.java

Lines changed: 112 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,32 @@
2323
*/
2424
public abstract class AbstractAppDeployer extends LoggingObject implements AppDeployer {
2525

26-
private ManageClient manageClient;
27-
private AdminManager adminManager;
28-
29-
/**
30-
* Can use this constructor when the default config used by ManageClient and AdminManager will work.
31-
*/
32-
public AbstractAppDeployer() {
33-
this(new ManageClient(), new AdminManager());
34-
}
35-
36-
public AbstractAppDeployer(ManageClient manageClient, AdminManager adminManager) {
37-
super();
38-
this.manageClient = manageClient;
39-
this.adminManager = adminManager;
40-
}
41-
42-
/**
43-
* The subclass just needs to define the list of commands to be invoked.
44-
*
45-
* @return
46-
*/
47-
protected abstract List<Command> getCommands();
26+
private ManageClient manageClient;
27+
private AdminManager adminManager;
28+
private List<DeployerListener> deployerListeners;
29+
30+
/**
31+
* Can use this constructor when the default config used by ManageClient and AdminManager will work.
32+
*/
33+
public AbstractAppDeployer() {
34+
this(new ManageClient(), new AdminManager());
35+
}
36+
37+
public AbstractAppDeployer(ManageClient manageClient, AdminManager adminManager) {
38+
super();
39+
this.manageClient = manageClient;
40+
this.adminManager = adminManager;
41+
42+
this.deployerListeners = new ArrayList<>();
43+
this.deployerListeners.add(new AddHostNameTokensDeployerListener());
44+
}
45+
46+
/**
47+
* The subclass just needs to define the list of commands to be invoked.
48+
*
49+
* @return
50+
*/
51+
protected abstract List<Command> getCommands();
4852

4953
/**
5054
* Calls execute on each of the configured commands.
@@ -56,23 +60,33 @@ public void deploy(AppConfig appConfig) {
5660
for (ConfigDir configDir : appConfig.getConfigDirs()) {
5761
configPaths.add(configDir.getBaseDir().getAbsolutePath());
5862
}
59-
logger.info(format("Deploying app %s with config dirs: %s\n", appConfig.getName(), configPaths));
63+
logger.info(format("Deploying app %s with config dirs: %s\n", appConfig.getName(), configPaths));
6064

61-
List<Command> commands = getCommands();
62-
Collections.sort(commands, new ExecuteComparator());
65+
List<Command> commands = getCommands();
66+
Collections.sort(commands, new ExecuteComparator());
6367

64-
CommandContext context = new CommandContext(appConfig, manageClient, adminManager);
68+
CommandContext context = new CommandContext(appConfig, manageClient, adminManager);
6569

66-
for (Command command : commands) {
67-
String name = command.getClass().getName();
68-
logger.info(format("Executing command [%s] with sort order [%d]", name, command.getExecuteSortOrder()));
69-
prepareCommand(command, context);
70-
executeCommand(command, context);
71-
logger.info(format("Finished executing command [%s]\n", name));
72-
}
70+
invokeDeployerListenersBeforeCommandsAreExecuted(new DeploymentContext(context, appConfig, commands));
7371

74-
logger.info(format("Deployed app %s", appConfig.getName()));
75-
}
72+
for (Command command : commands) {
73+
String name = command.getClass().getName();
74+
logger.info(format("Executing command [%s] with sort order [%d]", name, command.getExecuteSortOrder()));
75+
prepareCommand(command, context);
76+
executeCommand(command, context);
77+
logger.info(format("Finished executing command [%s]\n", name));
78+
}
79+
80+
logger.info(format("Deployed app %s", appConfig.getName()));
81+
}
82+
83+
protected void invokeDeployerListenersBeforeCommandsAreExecuted(DeploymentContext context) {
84+
if (deployerListeners != null) {
85+
for (DeployerListener listener : deployerListeners) {
86+
listener.beforeCommandsExecuted(context);
87+
}
88+
}
89+
}
7690

7791
/**
7892
* Prepare the given command before either execute or undo is called on it.
@@ -81,24 +95,24 @@ public void deploy(AppConfig appConfig) {
8195
* @param context
8296
*/
8397
protected void prepareCommand(Command command, CommandContext context) {
84-
if (command instanceof AbstractCommand) {
85-
AppConfig appConfig = context.getAppConfig();
86-
String[] filenamesToIgnore = appConfig.getResourceFilenamesToIgnore();
87-
Pattern excludePattern = appConfig.getResourceFilenamesExcludePattern();
88-
Pattern includePattern = appConfig.getResourceFilenamesIncludePattern();
89-
90-
AbstractCommand abstractCommand = (AbstractCommand)command;
91-
if (filenamesToIgnore != null) {
92-
abstractCommand.setFilenamesToIgnore(filenamesToIgnore);
93-
}
94-
if (excludePattern != null) {
95-
abstractCommand.setResourceFilenamesExcludePattern(excludePattern);
96-
}
97-
if (includePattern != null) {
98-
abstractCommand.setResourceFilenamesIncludePattern(includePattern);
99-
}
100-
}
101-
}
98+
if (command instanceof AbstractCommand) {
99+
AppConfig appConfig = context.getAppConfig();
100+
String[] filenamesToIgnore = appConfig.getResourceFilenamesToIgnore();
101+
Pattern excludePattern = appConfig.getResourceFilenamesExcludePattern();
102+
Pattern includePattern = appConfig.getResourceFilenamesIncludePattern();
103+
104+
AbstractCommand abstractCommand = (AbstractCommand) command;
105+
if (filenamesToIgnore != null) {
106+
abstractCommand.setFilenamesToIgnore(filenamesToIgnore);
107+
}
108+
if (excludePattern != null) {
109+
abstractCommand.setResourceFilenamesExcludePattern(excludePattern);
110+
}
111+
if (includePattern != null) {
112+
abstractCommand.setResourceFilenamesIncludePattern(includePattern);
113+
}
114+
}
115+
}
102116

103117
/**
104118
* Executes the command, catching an exception if desired.
@@ -107,16 +121,16 @@ protected void prepareCommand(Command command, CommandContext context) {
107121
* @param context
108122
*/
109123
protected void executeCommand(Command command, CommandContext context) {
110-
try {
111-
command.execute(context);
112-
} catch (RuntimeException ex) {
113-
if (context.getAppConfig().isCatchDeployExceptions()) {
114-
logger.error(format("Command [%s] threw exception that was caught; cause: %s", command.getClass().getName(), ex.getMessage()), ex);
115-
} else {
116-
throw ex;
117-
}
118-
}
119-
}
124+
try {
125+
command.execute(context);
126+
} catch (RuntimeException ex) {
127+
if (context.getAppConfig().isCatchDeployExceptions()) {
128+
logger.error(format("Command [%s] threw exception that was caught; cause: %s", command.getClass().getName(), ex.getMessage()), ex);
129+
} else {
130+
throw ex;
131+
}
132+
}
133+
}
120134

121135
/**
122136
* Calls undo on each of the configured commands that implements the UndoableCommand interface.
@@ -128,30 +142,30 @@ public void undeploy(AppConfig appConfig) {
128142
for (ConfigDir configDir : appConfig.getConfigDirs()) {
129143
configPaths.add(configDir.getBaseDir().getAbsolutePath());
130144
}
131-
logger.info(format("Undeploying app %s with config dirs: %s\n", appConfig.getName(), configPaths));
145+
logger.info(format("Undeploying app %s with config dirs: %s\n", appConfig.getName(), configPaths));
132146

133-
List<Command> commands = getCommands();
147+
List<Command> commands = getCommands();
134148

135-
List<UndoableCommand> undoableCommands = new ArrayList<UndoableCommand>();
136-
for (Command command : commands) {
137-
if (command instanceof UndoableCommand) {
138-
undoableCommands.add((UndoableCommand) command);
139-
}
140-
}
149+
List<UndoableCommand> undoableCommands = new ArrayList<UndoableCommand>();
150+
for (Command command : commands) {
151+
if (command instanceof UndoableCommand) {
152+
undoableCommands.add((UndoableCommand) command);
153+
}
154+
}
141155

142-
Collections.sort(undoableCommands, new UndoComparator());
143-
CommandContext context = new CommandContext(appConfig, manageClient, adminManager);
156+
Collections.sort(undoableCommands, new UndoComparator());
157+
CommandContext context = new CommandContext(appConfig, manageClient, adminManager);
144158

145-
for (UndoableCommand command : undoableCommands) {
146-
String name = command.getClass().getName();
147-
logger.info(format("Undoing command [%s] with sort order [%d]", name, command.getUndoSortOrder()));
148-
prepareCommand(command, context);
149-
undoCommand(command, context);
150-
logger.info(format("Finished undoing command [%s]\n", name));
151-
}
159+
for (UndoableCommand command : undoableCommands) {
160+
String name = command.getClass().getName();
161+
logger.info(format("Undoing command [%s] with sort order [%d]", name, command.getUndoSortOrder()));
162+
prepareCommand(command, context);
163+
undoCommand(command, context);
164+
logger.info(format("Finished undoing command [%s]\n", name));
165+
}
152166

153-
logger.info(format("Undeployed app %s", appConfig.getName()));
154-
}
167+
logger.info(format("Undeployed app %s", appConfig.getName()));
168+
}
155169

156170
/**
157171
* Calls undo on the command, catching an exception if desired.
@@ -170,18 +184,26 @@ protected void undoCommand(UndoableCommand command, CommandContext context) {
170184
}
171185
}
172186
}
187+
188+
public List<DeployerListener> getDeployerListeners() {
189+
return deployerListeners;
190+
}
191+
192+
public void setDeployerListeners(List<DeployerListener> deployerListeners) {
193+
this.deployerListeners = deployerListeners;
194+
}
173195
}
174196

175197
class ExecuteComparator implements Comparator<Command> {
176-
@Override
177-
public int compare(Command o1, Command o2) {
178-
return o1.getExecuteSortOrder().compareTo(o2.getExecuteSortOrder());
179-
}
198+
@Override
199+
public int compare(Command o1, Command o2) {
200+
return o1.getExecuteSortOrder().compareTo(o2.getExecuteSortOrder());
201+
}
180202
}
181203

182204
class UndoComparator implements Comparator<UndoableCommand> {
183-
@Override
184-
public int compare(UndoableCommand o1, UndoableCommand o2) {
185-
return o1.getUndoSortOrder().compareTo(o2.getUndoSortOrder());
186-
}
205+
@Override
206+
public int compare(UndoableCommand o1, UndoableCommand o2) {
207+
return o1.getUndoSortOrder().compareTo(o2.getUndoSortOrder());
208+
}
187209
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.marklogic.appdeployer.impl;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.mgmt.resource.hosts.HostManager;
5+
6+
import java.util.List;
7+
8+
public class AddHostNameTokensDeployerListener implements DeployerListener {
9+
10+
@Override
11+
public void beforeCommandsExecuted(DeploymentContext context) {
12+
AppConfig appConfig = context.getAppConfig();
13+
if (appConfig.isAddHostNameTokens()) {
14+
HostManager hostManager = new HostManager(context.getCommandContext().getManageClient());
15+
List<String> hostNames = hostManager.getHostNames();
16+
int size = hostNames.size();
17+
for (int i = 1; i <= size; i++) {
18+
appConfig.getCustomTokens().put("mlHostName" + i, hostNames.get(i - 1));
19+
}
20+
}
21+
}
22+
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.marklogic.appdeployer.impl;
2+
3+
/**
4+
* Provides an extension point for introducing behavior right before commands are executed by a subclass of
5+
* AbstractAppDeployer.
6+
*/
7+
public interface DeployerListener {
8+
9+
void beforeCommandsExecuted(DeploymentContext context);
10+
11+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.marklogic.appdeployer.impl;
2+
3+
import com.marklogic.appdeployer.AppConfig;
4+
import com.marklogic.appdeployer.command.Command;
5+
import com.marklogic.appdeployer.command.CommandContext;
6+
7+
import java.util.List;
8+
9+
/**
10+
* Intended to capture all inputs of interest before commands are executed so that an e.g. DeployerListener can fiddle
11+
* around with them.
12+
*/
13+
public class DeploymentContext {
14+
15+
private CommandContext commandContext;
16+
private AppConfig appConfig;
17+
private List<Command> commands;
18+
19+
public DeploymentContext(CommandContext commandContext, AppConfig appConfig, List<Command> commands) {
20+
this.commandContext = commandContext;
21+
this.appConfig = appConfig;
22+
this.commands = commands;
23+
}
24+
25+
public CommandContext getCommandContext() {
26+
return commandContext;
27+
}
28+
29+
public void setCommandContext(CommandContext commandContext) {
30+
this.commandContext = commandContext;
31+
}
32+
33+
public AppConfig getAppConfig() {
34+
return appConfig;
35+
}
36+
37+
public void setAppConfig(AppConfig appConfig) {
38+
this.appConfig = appConfig;
39+
}
40+
41+
public List<Command> getCommands() {
42+
return commands;
43+
}
44+
45+
public void setCommands(List<Command> commands) {
46+
this.commands = commands;
47+
}
48+
}

src/test/java/com/marklogic/appdeployer/DefaultAppConfigFactoryTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ public void cpfDatabaseName() {
162162
public void allProperties() {
163163
Properties p = new Properties();
164164

165+
p.setProperty("mlAddHostNameTokens", "true");
165166
p.setProperty("mlCatchDeployExceptions", "true");
166167
p.setProperty("mlCatchUndeployExceptions", "true");
167168

@@ -265,6 +266,7 @@ public void allProperties() {
265266
sut = new DefaultAppConfigFactory(new SimplePropertySource(p));
266267
AppConfig config = sut.newAppConfig();
267268

269+
assertTrue(config.isAddHostNameTokens());
268270
assertTrue(config.isCatchDeployExceptions());
269271
assertTrue(config.isCatchUndeployExceptions());
270272

0 commit comments

Comments
 (0)