View Javadoc

1   package org.kuali.common.deploy.spring;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.List;
6   import java.util.Properties;
7   
8   import org.codehaus.plexus.util.StringUtils;
9   import org.kuali.common.deploy.AppDynamicsMonitoring;
10  import org.kuali.common.deploy.ApplicationServer;
11  import org.kuali.common.deploy.DefaultDeployService;
12  import org.kuali.common.deploy.DeployContext;
13  import org.kuali.common.deploy.DeployService;
14  import org.kuali.common.deploy.Deployable;
15  import org.kuali.common.deploy.MachineAgent;
16  import org.kuali.common.deploy.Monitoring;
17  import org.kuali.common.deploy.ServerAgent;
18  import org.kuali.common.deploy.SysAdminExecutable;
19  import org.kuali.common.deploy.TomcatApplicationServer;
20  import org.kuali.common.http.HttpContext;
21  import org.kuali.common.http.HttpWaitExecutable;
22  import org.kuali.common.util.Artifact;
23  import org.kuali.common.util.LocationUtils;
24  import org.kuali.common.util.PropertyUtils;
25  import org.kuali.common.util.UnixCmds;
26  import org.kuali.common.util.secure.DefaultSecureChannel;
27  import org.kuali.common.util.secure.SecureChannel;
28  import org.kuali.common.util.spring.ArtifactFilenameFactoryBean;
29  import org.kuali.common.util.spring.ArtifactPathFactoryBean;
30  import org.kuali.common.util.spring.SpringUtils;
31  import org.springframework.beans.factory.annotation.Autowired;
32  import org.springframework.context.annotation.Bean;
33  import org.springframework.context.annotation.Configuration;
34  import org.springframework.context.annotation.Import;
35  import org.springframework.core.env.ConfigurableEnvironment;
36  
37  @Configuration
38  @Import({ SqlControllerConfig.class })
39  public class DeployConfig {
40  
41  	@Autowired
42  	ConfigurableEnvironment env;
43  
44  	@Autowired
45  	SqlControllerConfig sqlController;
46  
47  	protected Artifact getJdbcDriverArtifact() {
48  		Artifact a = new Artifact();
49  		a.setGroupId(SpringUtils.getProperty(env, "jdbc.driver.groupId"));
50  		a.setArtifactId(SpringUtils.getProperty(env, "jdbc.driver.artifactId"));
51  		a.setVersion(SpringUtils.getProperty(env, "jdbc.driver.version"));
52  		a.setType("jar");
53  		return a;
54  	}
55  
56  	protected Artifact getpplicationArtifact() {
57  		Artifact a = new Artifact();
58  		a.setGroupId(SpringUtils.getProperty(env, "project.groupId"));
59  		a.setArtifactId(SpringUtils.getProperty(env, "project.artifactId"));
60  		a.setVersion(SpringUtils.getProperty(env, "project.version"));
61  		a.setClassifier(SpringUtils.getProperty(env, "project.classifier", "NONE"));
62  		a.setType("war");
63  		return a;
64  	}
65  
66  	protected DeployContext getDeployContext() {
67  		DeployContext ctx = new DeployContext();
68  		ctx.setEnvironment(SpringUtils.getProperty(env, "deploy.env"));
69  		ctx.setHostname(SpringUtils.getProperty(env, "kdo.channel.hostname"));
70  		ctx.setUsername(SpringUtils.getProperty(env, "kdo.channel.username"));
71  		ctx.setJdbcDriver(getJdbcDriverArtifact());
72  		ctx.setApplication(getpplicationArtifact());
73  		ctx.setConfigFiles(getApplicationConfig());
74  		return ctx;
75  	}
76  
77  	@Bean
78  	public SecureChannel kdoSecureChannel() {
79  		DeployContext ctx = getDeployContext();
80  		DefaultSecureChannel dsc = new DefaultSecureChannel();
81  		dsc.setUsername(ctx.getUsername());
82  		dsc.setHostname(ctx.getHostname());
83  		dsc.setStrictHostKeyChecking(SpringUtils.getBoolean(env, "kdo.channel.strictHostKeyChecking", false));
84  		dsc.setUseConfigFile(SpringUtils.getBoolean(env, "kdo.channel.useConfigFile", false));
85  		dsc.setIncludeDefaultPrivateKeyLocations(SpringUtils.getBoolean(env, "kdo.channel.includeDefaultPrivateKeyLocations", false));
86  		dsc.setPrivateKeyStrings(Arrays.asList(SpringUtils.getProperty(env, "kdo.channel.privateKey")));
87  		return dsc;
88  	}
89  
90  	protected List<String> getTomcatDeletes() {
91  		// /usr/local/tomcat/lib
92  		String lib = SpringUtils.getProperty(env, "tomcat.lib");
93  
94  		// rm -rf gets invoked on all of these
95  		List<String> pathsToDelete = new ArrayList<String>();
96  		pathsToDelete.add(lib + "/mysql*.jar");
97  		pathsToDelete.add(lib + "/ojdbc*.jar");
98  		pathsToDelete.add(lib + "/classes12*.jar");
99  		pathsToDelete.add(lib + "/orai18n*.jar");
100 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.setenv"));
101 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.home.org"));
102 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.home.org.alt"));
103 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.conf.catalina"));
104 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.logs"));
105 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.webapps"));
106 		pathsToDelete.add(SpringUtils.getProperty(env, "tomcat.work"));
107 		return pathsToDelete;
108 	}
109 
110 	protected List<String> getTomcatCreates() {
111 		// mkdir -p gets invoked on all of these
112 		List<String> dirsToCreate = new ArrayList<String>();
113 		dirsToCreate.add(SpringUtils.getProperty(env, "tomcat.logs"));
114 		dirsToCreate.add(SpringUtils.getProperty(env, "tomcat.webapps"));
115 		dirsToCreate.add(SpringUtils.getProperty(env, "tomcat.conf.catalina"));
116 		return dirsToCreate;
117 	}
118 
119 	protected List<String> getTomcatChowns() {
120 		// chown -L -R gets invoked on all of these
121 		List<String> pathsToChown = new ArrayList<String>();
122 		pathsToChown.add(SpringUtils.getProperty(env, "tomcat.base"));
123 		pathsToChown.add(SpringUtils.getProperty(env, "tomcat.home"));
124 		return pathsToChown;
125 	}
126 
127 	protected List<Deployable> getTomcatDeployables() {
128 		// Tomcat related files that get deployed
129 		List<Deployable> deployables = new ArrayList<Deployable>();
130 		deployables.add(getSetEnv());
131 		deployables.addAll(getJsps());
132 		deployables.addAll(getApplicationConfig());
133 		deployables.add(getJdbcDriver());
134 		return deployables;
135 	}
136 
137 	@Bean
138 	public Properties kdoFilterProperties() {
139 		return SpringUtils.getAllEnumerableProperties(env);
140 	}
141 
142 	protected ApplicationServer getApplicationServer() {
143 		// rm -rf gets invoked on all of these
144 		List<String> pathsToDelete = getTomcatDeletes();
145 
146 		// mkdir -p gets invoked on all of these
147 		List<String> dirsToCreate = getTomcatCreates();
148 
149 		// chown -L -R gets invoked on all of these
150 		List<String> pathsToChown = getTomcatChowns();
151 
152 		// Tomcat related files that get deployed
153 		List<Deployable> deployables = getTomcatDeployables();
154 
155 		// The war files can be quite large ~100mb's
156 		// This flag provides a simple way to skip the overhead of uploading a war file
157 		boolean skipWar = SpringUtils.getBoolean(env, "tomcat.war.skip", false);
158 		if (!skipWar) {
159 			deployables.add(getApplication());
160 		}
161 
162 		// If true, skip transferring all tomcat related files to the remote machine
163 		boolean skipFiles = SpringUtils.getBoolean(env, "tomcat.files.skip", false);
164 
165 		// Setup Tomcat with what it needs to stop/prepare/start correctly
166 		TomcatApplicationServer tomcat = new TomcatApplicationServer();
167 		tomcat.setChannel(kdoSecureChannel());
168 		tomcat.setUsername(SpringUtils.getProperty(env, "tomcat.user"));
169 		tomcat.setGroup(SpringUtils.getProperty(env, "tomcat.group"));
170 		tomcat.setShutdown(SpringUtils.getProperty(env, "tomcat.shutdown"));
171 		tomcat.setStartup(SpringUtils.getProperty(env, "tomcat.startup"));
172 		tomcat.setPathsToDelete(pathsToDelete);
173 		tomcat.setDirsToCreate(dirsToCreate);
174 		tomcat.setDeployables(deployables);
175 		tomcat.setPathsToChown(pathsToChown);
176 		tomcat.setSkipFiles(skipFiles);
177 		tomcat.setFilterProperties(kdoFilterProperties());
178 		tomcat.setHttpWait(getHttpWaitExecutable());
179 		return tomcat;
180 	}
181 
182 	protected Deployable getSetEnv() {
183 		Deployable d = new Deployable();
184 		d.setRemote(SpringUtils.getProperty(env, "tomcat.setenv"));
185 		d.setLocal(SpringUtils.getProperty(env, "tomcat.setenv.local"));
186 		d.setFilter(true);
187 		d.setPermissions("755");
188 		return d;
189 	}
190 
191 	protected Deployable getMachineAgentController() {
192 		Deployable d = new Deployable();
193 		d.setRemote(SpringUtils.getProperty(env, "appdynamics.ma.controller"));
194 		d.setLocal(SpringUtils.getProperty(env, "appdynamics.ma.controller.local"));
195 		d.setFilter(true);
196 		return d;
197 	}
198 
199 	protected Deployable getServerAgentController() {
200 		Deployable d = new Deployable();
201 		d.setRemote(SpringUtils.getProperty(env, "appdynamics.sa.controller"));
202 		d.setLocal(SpringUtils.getProperty(env, "appdynamics.sa.controller.local"));
203 		d.setFilter(true);
204 		return d;
205 	}
206 
207 	protected List<Deployable> getJsps() {
208 		Deployable environment = new Deployable();
209 		environment.setRemote(SpringUtils.getProperty(env, "tomcat.jsp.env"));
210 		environment.setLocal(SpringUtils.getProperty(env, "tomcat.jsp.env.local"));
211 
212 		Deployable tail = new Deployable();
213 		tail.setRemote(SpringUtils.getProperty(env, "tomcat.jsp.tail"));
214 		tail.setLocal(SpringUtils.getProperty(env, "tomcat.jsp.tail.local"));
215 
216 		List<Deployable> jsps = new ArrayList<Deployable>();
217 		jsps.add(environment);
218 		jsps.add(tail);
219 		return jsps;
220 	}
221 
222 	protected String getJdbcDriverFilename() {
223 		Artifact jdbcDriver = getJdbcDriverArtifact();
224 
225 		ArtifactFilenameFactoryBean factory = new ArtifactFilenameFactoryBean();
226 		factory.setGroupId(jdbcDriver.getGroupId());
227 		factory.setArtifactId(jdbcDriver.getArtifactId());
228 		factory.setVersion(jdbcDriver.getVersion());
229 		factory.setType(jdbcDriver.getType());
230 		return factory.getObject();
231 	}
232 
233 	protected String getJdbcDriverPath() {
234 		Artifact jdbcDriver = getJdbcDriverArtifact();
235 		ArtifactPathFactoryBean factory = new ArtifactPathFactoryBean();
236 		factory.setGroupId(jdbcDriver.getGroupId());
237 		factory.setArtifactId(jdbcDriver.getArtifactId());
238 		factory.setVersion(jdbcDriver.getVersion());
239 		factory.setType(jdbcDriver.getType());
240 		return factory.getObject();
241 	}
242 
243 	protected String getApplicationPath() {
244 		Artifact app = getpplicationArtifact();
245 		ArtifactPathFactoryBean factory = new ArtifactPathFactoryBean();
246 		factory.setGroupId(app.getGroupId());
247 		factory.setArtifactId(app.getArtifactId());
248 		factory.setVersion(app.getVersion());
249 		factory.setType(app.getType());
250 		factory.setMustExist(true);
251 		return factory.getObject();
252 	}
253 
254 	protected Deployable getJdbcDriver() {
255 		String lib = SpringUtils.getProperty(env, "tomcat.lib");
256 		Deployable d = new Deployable();
257 		d.setRemote(lib + "/" + getJdbcDriverFilename());
258 		d.setLocal(getJdbcDriverPath());
259 		return d;
260 	}
261 
262 	protected Deployable getApplication() {
263 		Deployable d = new Deployable();
264 		d.setRemote(SpringUtils.getProperty(env, "tomcat.root.war"));
265 		d.setLocal(getApplicationPath());
266 		return d;
267 	}
268 
269 	protected List<Deployable> getApplicationConfig() {
270 		Properties properties = SpringUtils.getAllEnumerableProperties(env);
271 		Properties configProperties = PropertyUtils.getProperties(properties, "kdo.config.*.local", null);
272 		List<String> keys = PropertyUtils.getSortedKeys(configProperties);
273 		List<Deployable> deployables = new ArrayList<Deployable>();
274 		for (String key : keys) {
275 			Deployable deployable = getApplicationConfig(key);
276 			if (deployable != null) {
277 				deployables.add(deployable);
278 			}
279 		}
280 		return deployables;
281 	}
282 
283 	protected Deployable getApplicationConfig(String localKey) {
284 		// kdo.config.1.local
285 		String[] tokens = StringUtils.split(localKey, ".");
286 
287 		// Should always be 4 tokens
288 		if (tokens.length != 4) {
289 			throw new IllegalStateException("Expected 4 tokens [" + localKey + "]");
290 		}
291 
292 		// Third token should be a unique identifier for this config file
293 		String identifier = tokens[2];
294 
295 		// Assemble property keys
296 		String remoteKey = "kdo.config." + identifier + ".remote";
297 		String filterKey = "kdo.config." + identifier + ".filter";
298 		String requiredKey = "kdo.config." + identifier + ".required";
299 
300 		// Extract information using the property keys
301 		String local = SpringUtils.getProperty(env, localKey);
302 		String remote = SpringUtils.getProperty(env, remoteKey);
303 		boolean filter = SpringUtils.getBoolean(env, filterKey, true);
304 		boolean required = SpringUtils.getBoolean(env, requiredKey, true);
305 
306 		// Check to see if the resource exists
307 		boolean exists = LocationUtils.exists(local);
308 
309 		// If it is required but does not exist, we have a problem
310 		if (required && !exists) {
311 			throw new IllegalStateException("[" + local + "] is required, but does not exist");
312 		}
313 
314 		// It's not required and does not exist, skip it
315 		if (!exists) {
316 			return null;
317 		}
318 
319 		// Create a new deployable from the information we gathered from the environment
320 		Deployable d = new Deployable();
321 		d.setRemote(remote);
322 		d.setLocal(local);
323 		d.setFilter(filter);
324 		return d;
325 	}
326 
327 	protected HttpWaitExecutable getHttpWaitExecutable() {
328 		// Extract properties from the environment
329 		Long overallTimeoutMillis = SpringUtils.getMillis(env, "http.overallTimeout", "30m");
330 		Long requestTimeoutMillis = SpringUtils.getMillis(env, "http.requestTimeout", "15s");
331 		String url = SpringUtils.getProperty(env, "http.url");
332 		boolean skip = SpringUtils.getBoolean(env, "http.wait.skip", false);
333 
334 		// Setup the context
335 		HttpContext context = new HttpContext();
336 		context.setUrl(url);
337 		context.setOverallTimeoutMillis(overallTimeoutMillis.intValue());
338 		context.setRequestTimeoutMillis(requestTimeoutMillis.intValue());
339 
340 		// Setup the executable
341 		HttpWaitExecutable executable = new HttpWaitExecutable();
342 		executable.setContext(context);
343 		executable.setSkip(skip);
344 		return executable;
345 	}
346 
347 	protected MachineAgent getMachineAgent() {
348 		MachineAgent agent = new MachineAgent();
349 		agent.setStartupCommand(SpringUtils.getProperty(env, "appdynamics.ma.cmd"));
350 		agent.setBaseDir(SpringUtils.getProperty(env, "appdynamics.ma.base"));
351 		agent.setTmpDir(SpringUtils.getProperty(env, "appdynamics.ma.tmp"));
352 		agent.setLogsDir(SpringUtils.getProperty(env, "appdynamics.ma.logs"));
353 		agent.setController(getMachineAgentController());
354 		agent.setLogFile(SpringUtils.getProperty(env, "appdynamics.ma.logFile"));
355 		agent.setStartupToken(SpringUtils.getProperty(env, "appdynamics.ma.logFile.startupToken"));
356 		agent.setStartupTimeoutMillis(new Long(SpringUtils.getMillis(env, "appdynamics.ma.logFile.monitor.timeout", "5m")).intValue());
357 		agent.setLogFileIntervalMillis(new Long(SpringUtils.getMillis(env, "appdynamics.ma.logFile.monitor.interval", "500ms")).intValue());
358 		agent.setLogFileEncoding(SpringUtils.getProperty(env, "appdynamics.ma.logFile.encoding"));
359 		return agent;
360 	}
361 
362 	protected ServerAgent getServerAgent() {
363 		ServerAgent agent = new ServerAgent();
364 		agent.setAppServerStartupOptions(SpringUtils.getProperty(env, "appdynamics.sa.tomcat.java.options"));
365 		agent.setBaseDir(SpringUtils.getProperty(env, "appdynamics.sa.base"));
366 		agent.setLogsDir(SpringUtils.getProperty(env, "appdynamics.sa.logs"));
367 		agent.setController(getServerAgentController());
368 		return agent;
369 	}
370 
371 	protected Monitoring getMonitoring() {
372 		boolean enabled = SpringUtils.getBoolean(env, "monitoring.enabled", false);
373 		AppDynamicsMonitoring adm = new AppDynamicsMonitoring();
374 		adm.setUser(SpringUtils.getProperty(env, "tomcat.user"));
375 		adm.setGroup(SpringUtils.getProperty(env, "tomcat.group"));
376 		adm.setChannel(kdoSecureChannel());
377 		adm.setMachineAgent(getMachineAgent());
378 		adm.setServerAgent(getServerAgent());
379 		adm.setEnabled(enabled);
380 		adm.setFilterProperties(kdoFilterProperties());
381 		return adm;
382 	}
383 
384 	protected SysAdminExecutable getSysAdminExecutable() {
385 		boolean skip = SpringUtils.getBoolean(env, "sysadmin.skip", false);
386 		String hostname = SpringUtils.getProperty(env, "dns.hostname");
387 		UnixCmds cmds = new UnixCmds();
388 		List<String> commands = Arrays.asList(cmds.hostname(hostname));
389 		SysAdminExecutable sysadmin = new SysAdminExecutable();
390 		sysadmin.setChannel(kdoSecureChannel());
391 		sysadmin.setCommands(commands);
392 		sysadmin.setSkip(skip);
393 		return sysadmin;
394 	}
395 
396 	@Bean(initMethod = "deploy")
397 	public DeployService kdoDeployService() {
398 		DefaultDeployService dds = new DefaultDeployService();
399 		dds.setChannel(kdoSecureChannel());
400 		dds.setMonitoring(getMonitoring());
401 		dds.setAppServer(getApplicationServer());
402 		dds.setDatabaseResetExecutable(sqlController.sqlExecutable());
403 		dds.setContext(getDeployContext());
404 		dds.setSysAdminExecutable(getSysAdminExecutable());
405 		return dds;
406 	}
407 
408 }