org.fusesource.fabric.commands.ContainerConnect Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fabric-commands Show documentation
Show all versions of fabric-commands Show documentation
Fuse Fabric :: Karaf Commands
The newest version!
/**
* Copyright (C) FuseSource, Inc.
* http://fusesource.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 org.fusesource.fabric.commands;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.Option;
import org.apache.felix.service.command.CommandSession;
import org.apache.karaf.shell.console.BlueprintContainerAware;
import org.apache.karaf.shell.console.jline.Console;
import org.apache.sshd.ClientChannel;
import org.apache.sshd.ClientSession;
import org.apache.sshd.SshClient;
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.common.util.NoCloseInputStream;
import org.apache.sshd.common.util.NoCloseOutputStream;
import org.fusesource.fabric.api.Container;
import org.fusesource.fabric.api.FabricAuthenticationException;
import org.fusesource.fabric.boot.commands.support.FabricCommand;
import org.fusesource.fabric.utils.shell.ShellUtils;
import org.osgi.service.blueprint.container.BlueprintContainer;
import static org.fusesource.fabric.utils.FabricValidations.validateContainersName;
@Command(name = "container-connect", scope = "fabric", description = "Connect to a remote container")
public class ContainerConnect extends FabricCommand implements BlueprintContainerAware {
@Option(name="-u", aliases={"--username"}, description="Remote user name", required = false, multiValued = false)
private String username;
@Option(name="-p", aliases={"--password"}, description="Remote user password", required = false, multiValued = false)
private String password;
@Argument(index = 0, name="container", description="The container name", required = true, multiValued = false)
private String container = null;
@Argument(index = 1, name = "command", description = "Optional command to execute", required = false, multiValued = true)
private List command;
private BlueprintContainer blueprintContainer;
private ClientSession sshSession;
private String sshClientId;
protected Object doExecute() throws Exception {
checkFabricAvailable();
validateContainersName(container);
String cmdStr = "";
if (command != null) {
StringBuilder sb = new StringBuilder();
for (String cmd : command) {
if (sb.length() > 0) {
sb.append(' ');
}
sb.append(cmd);
}
sb.append("\n");
cmdStr = sb.toString();
}
Container found = getContainer(container);
String sshUrl = found.getSshUrl();
if (sshUrl == null) {
throw new IllegalArgumentException("Container " + container + " has no SSH URL.");
}
String[] ssh = sshUrl.split(":");
if (ssh.length < 2) {
throw new IllegalArgumentException("Container " + container + " has an invalid SSH URL '" + sshUrl + "'");
}
username = username != null && !username.isEmpty() ? username : ShellUtils.retrieveFabricUser(session);
password = password != null ? password : ShellUtils.retrieveFabricUserPassword(session);
try {
executSshCommand(session, username, password, ssh[0], ssh[1], cmdStr);
} catch (FabricAuthenticationException ex) {
username = null;
password = null;
promptForSshCredentialsIfNeeded();
executSshCommand(session, username, password, ssh[0], ssh[1], cmdStr);
}
return null;
}
/**
* Executes the ssh command.
*
* @param session
* @param username
* @param password
* @param hostname
*@param port
* @param cmd @throws Exception
*/
private void executSshCommand(CommandSession session, String username, String password, String hostname, String port, String cmd) throws Exception {
// Create the client from prototype
SshClient client = getSshClient(blueprintContainer, sshClientId);
String agentSocket = null;
if (this.session.get(SshAgent.SSH_AUTHSOCKET_ENV_NAME) != null) {
agentSocket = this.session.get(SshAgent.SSH_AUTHSOCKET_ENV_NAME).toString();
client.getProperties().put(SshAgent.SSH_AUTHSOCKET_ENV_NAME,agentSocket);
}
try {
ConnectFuture future = client.connect(hostname, Integer.parseInt(port));
future.await();
sshSession = future.getSession();
Object oldIgnoreInterrupts = this.session.get(Console.IGNORE_INTERRUPTS);
this.session.put( Console.IGNORE_INTERRUPTS, Boolean.TRUE );
try {
System.out.println("Connected");
boolean authed = false;
/**
if (agentSocket != null) {
sshSession.authAgent(username);
int ret = sshSession.waitFor(ClientSession.WAIT_AUTH | ClientSession.CLOSED | ClientSession.AUTHED, 0);
if ((ret & ClientSession.AUTHED) == 0) {
System.err.println("Agent authentication failed, falling back to password authentication.");
} else {
authed = true;
}
}*/
if (!authed) {
if (username == null) {
throw new FabricAuthenticationException("No username specified.");
}
log.debug("Prompting user for password");
String pwd = password != null ? password : ShellUtils.readLine(session, "Password: ", true);
sshSession.authPassword(username, pwd);
int ret = sshSession.waitFor(ClientSession.WAIT_AUTH | ClientSession.CLOSED | ClientSession.AUTHED, 0);
if ((ret & ClientSession.AUTHED) == 0) {
System.err.println("Password authentication failed");
} else {
authed = true;
}
}
if (!authed) {
throw new FabricAuthenticationException("Failed to authenticate.");
}
//If user is authenticated credentials to session for future use.
ShellUtils.storeFabricCredentials(session, username, password);
ClientChannel channel;
if (cmd != null && cmd.length() > 0) {
channel = sshSession.createChannel("exec", cmd);
channel.setIn(new ByteArrayInputStream(new byte[0]));
} else {
channel = sshSession.createChannel("shell");
channel.setIn(new NoCloseInputStream(System.in));
((ChannelShell) channel).setPtyColumns(ShellUtils.getTermWidth(session));
((ChannelShell) channel).setupSensibleDefaultPty();
((ChannelShell) channel).setAgentForwarding(true);
}
channel.setOut(new NoCloseOutputStream(System.out));
channel.setErr(new NoCloseOutputStream(System.err));
channel.open();
channel.waitFor(ClientChannel.CLOSED, 0);
} finally {
session.put(Console.IGNORE_INTERRUPTS, oldIgnoreInterrupts);
sshSession.close(false);
}
} finally {
client.stop();
}
}
/**
* Prompts the user for username & password.
* @throws IOException
*/
private void promptForSshCredentialsIfNeeded() throws IOException {
// If the username was not configured via cli, then prompt the user for the values
if (username == null || username.isEmpty()) {
log.debug("Prompting user for ssh login");
username = ShellUtils.readLine(session, "SSH Login for " + container + ": ", false);
}
if (password == null) {
password = ShellUtils.readLine(session, "SSH Password for " + username + "@" + container + ": ", true);
}
}
private SshClient getSshClient(BlueprintContainer blueprintContainer, String clientId) {
// Create the client from prototype
SshClient client = (SshClient) blueprintContainer.getComponentInstance(clientId);
log.debug("Created client: {}", client);
client.start();
return client;
}
public void setBlueprintContainer(final BlueprintContainer blueprintContainer) {
assert blueprintContainer != null;
this.blueprintContainer = blueprintContainer;
}
public void setSshClientId(String sshClientId) {
this.sshClientId = sshClientId;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy