
com.groupon.deployment.host.Roller Maven / Gradle / Ivy
/**
* Copyright 2015 Groupon.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.groupon.deployment.host;
import akka.actor.AbstractActor;
import com.google.common.base.Charsets;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import com.groupon.deployment.HostDeploymentNotifications;
import com.groupon.deployment.SshSessionFactory;
import com.typesafe.config.Config;
import models.Host;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.connection.channel.direct.Session;
import play.Logger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;
/**
* Roller deployment actor.
*
* @author Brandon Arp (barp at groupon dot com)
*/
public class Roller extends AbstractActor {
/**
* Public constructor.
*
* @param host host to deploy to
* @param sshFactory factory for ssh connections
* @param config artemis configuration
*/
@AssistedInject
public Roller(
@Assisted final Host host,
final SshSessionFactory sshFactory,
final Config config) {
_host = host;
_sshFactory = sshFactory;
_config = config;
Logger.info("Started roller deployment actor for host " + host.getName());
context().parent().tell(new HostDeploymentNotifications.DeploymentStarted(host), self());
self().tell("start", self());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("start", start -> {
final String dc = _host.getName().substring(_host.getName().lastIndexOf('.') + 1);
String baseUrl = _config.getString("roller.artemisBaseUrl." + dc);
if (baseUrl == null) {
baseUrl = _config.getString("roller.artemisBaseUrl.default");
}
try (SSHClient sshClient = _sshFactory.create(_host.getName())) {
// Pre-roll scripts
executeCommand(sshClient, "sudo /usr/local/bin/beforeRoll 2>&1");
// Roll
executeRequired(sshClient, "sudo /var/tmp/roll --baseurl " + baseUrl + " 2>&1", "roller");
// Verify
executeRequired(sshClient, "sudo /usr/local/bin/verifyRoll 2>&1", "verify roll script");
// Post-roll scripts
executeRequired(sshClient, "sudo /usr/local/bin/afterRoll 2>&1", "post-roll script");
context().parent().tell(new HostDeploymentNotifications.DeploymentSucceeded(_host), self());
// CHECKSTYLE.OFF: IllegalCatch - we need to catch everything, we'll record it and die
} catch (final IOException | RuntimeException e) {
// CHECKSTYLE.ON: IllegalCatch
context().parent().tell(new HostDeploymentNotifications.DeploymentFailed(_host, e), self());
}
})
.build();
}
private void executeRequired(final SSHClient sshClient, final String commandString, final String description) throws IOException {
final Integer exitStatus;
exitStatus = executeCommand(sshClient, commandString);
if (exitStatus == null || exitStatus != 0) {
throw new IllegalStateException(description + " exit code was " + exitStatus);
}
}
private Integer executeCommand(final SSHClient sshClient, final String commandString) throws IOException {
context().parent().tell(new HostDeploymentNotifications.DeploymentLog(_host, "Executing '" + commandString + "'"), self());
final Integer exitStatus;
try (Session session = sshClient.startSession();
Session.Command command = session.exec(commandString);
BufferedReader error = new BufferedReader(new InputStreamReader(command.getErrorStream(), Charsets.UTF_8));
BufferedReader reader = new BufferedReader(new InputStreamReader(command.getInputStream(), Charsets.UTF_8))) {
String line = reader.readLine();
while (line != null) {
Logger.info("***" + line);
context().parent().tell(new HostDeploymentNotifications.DeploymentLog(_host, line), self());
line = reader.readLine();
}
command.join(30, TimeUnit.SECONDS);
session.join(30, TimeUnit.SECONDS);
exitStatus = command.getExitStatus();
}
return exitStatus;
}
private final Host _host;
private final SshSessionFactory _sshFactory;
private final Config _config;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy