Host SSH Options

This commit is contained in:
Michael Woodward 2017-04-12 19:07:59 +01:00
parent 542e5f0dc2
commit 54b683c556
3 changed files with 114 additions and 41 deletions

View File

@ -9,6 +9,7 @@ namespace Deployer\Host;
use Deployer\Configuration\Configuration;
use Deployer\Configuration\ConfigurationAccessor;
use Deployer\Ssh\Options;
class Host
{
@ -21,7 +22,7 @@ class Host
private $identityFile;
private $forwardAgent = true;
private $multiplexing = null;
private $options = [];
private $options;
/**
* @param string $hostname
@ -30,35 +31,27 @@ class Host
{
$this->hostname = $hostname;
$this->config = new Configuration();
$this->options = $this->initOptions();
}
/**
* Generate options string for ssh
*
* @return string
*/
public function sshOptions()
private function initOptions() : Options
{
$options = '';
$options = new Options;
if ($this->port) {
$options .= " -p {$this->port}";
$options = $options->withOption('-p', $this->port);
}
if ($this->configFile) {
$options .= " -F {$this->configFile}";
$options = $options->withOption('-F', $this->configFile);
}
if ($this->identityFile) {
$options .= " -i {$this->identityFile}";
$options = $options->withOption('-i', $this->identityFile);
}
if ($this->forwardAgent) {
$options .= " -A";
}
foreach ($this->options as $option) {
$options .= " -o $option";
$options = $options->withFlag('-A');
}
return $options;
@ -202,31 +195,32 @@ class Host
return $this;
}
/**
* @return array
*/
public function getOptions()
public function getOptions() : Options
{
return $this->options;
}
/**
* @param array $options
* @return $this
*/
public function options(array $options)
public function options(array $options) : Host
{
$this->options = $options;
$this->options = $this->options->withOptions($options);
return $this;
}
/**
* @param string $option
* @return $this
*/
public function addOption(string $option)
public function flags(array $flags) : Host
{
$this->options[] = $option;
$this->options = $this->options->withFlags($flags);
return $this;
}
public function addOption(string $option, $value) : Host
{
$this->options = $this->options->withOption($option, $value);
return $this;
}
public function addFlag(string $flag) : Host
{
$this->options = $this->options->withFlag($flag);
return $this;
}

View File

@ -56,17 +56,17 @@ class Client
$this->pop->command($hostname, $command);
$options = $host->sshOptions();
$options = $host->getOptions();
$become = $host->has('become') ? 'sudo -u ' . $host->get('become') : '';
// When tty need to be allocated, don't use multiplexing,
// and pass command without bash allocation on remote host.
if ($config['tty']) {
$this->output->write(''); // Notify OutputWatcher
$options .= ' -tt';
$options = $options->withFlag('-tt');
$command = escapeshellarg($command);
$ssh = "ssh $options $host $command";
$ssh = "ssh {$options->getOptionsString()} $host $command";
$process = new Process($ssh);
$process
->setTimeout($config['timeout'])
@ -80,7 +80,7 @@ class Client
$options = $this->initMultiplexing($host);
}
$ssh = "ssh $options $host $become 'bash -s; printf \"[exit_code:%s]\" $?;'";
$ssh = "ssh {$options->getOptionsString()} $host $become 'bash -s; printf \"[exit_code:%s]\" $?;'";
$process = new Process($ssh);
$process
@ -126,14 +126,18 @@ class Client
*/
private function initMultiplexing(Host $host)
{
$options = $host->sshOptions();
$options = $host->getOptions();
$controlPath = $this->generateControlPath($host);
$options .= " -o ControlMaster=auto";
$options .= " -o ControlPersist=60";
$options .= " -o ControlPath=$controlPath";
$multiplexDefaults = (new Options)->withOptions([
'-o ControlMaster' => 'auto',
'-o ControlPersist' => '60',
'-o ControlPath' => $controlPath,
]);
$process = new Process("ssh $options -O check -S $controlPath $host 2>&1");
$options = $options->withDefaults($multiplexDefaults);
$process = new Process("ssh {$options->getOptionsString()} -O check -S $controlPath $host 2>&1");
$process->run();
if (!preg_match('/Master running/', $process->getOutput()) && $this->output->isVeryVerbose()) {

75
src/Ssh/Options.php Normal file
View File

@ -0,0 +1,75 @@
<?php
namespace Deployer\Ssh;
/**
* @author Michael Woodward <mikeymike.mw@gmail.com>
*/
class Options
{
/**
* @var array
*/
private $flags = [];
/**
* @var array
*/
private $options = [];
public function getOptionsString() : string
{
$flags = implode(' ', $this->flags);
$options = implode(' ', array_map(function ($key, $value) {
return sprintf('%s=%s', $key, $value);
}, array_keys($this->options), $this->options));
return sprintf('%s %s', $flags, $options);
}
public function withFlags(array $flags) : Options
{
$clone = clone $this;
$clone->flags = $flags;
return $clone;
}
public function withOptions(array $options) : Options
{
$clone = clone $this;
$clone->options = $options;
return $clone;
}
public function withFlag($flag) : Options
{
$clone = clone $this;
$clone->flags = array_unique(array_merge($this->flags, [$flag]));
return $clone;
}
public function withOption(string $option, string $value) : Options
{
$clone = clone $this;
$clone->options = array_merge($this->options, [$option => $value]);
return $clone;
}
public function withDefaults(Options $defaultOptions) : Options
{
$clone = clone $this;
$clone->flags = array_merge($defaultOptions->flags, $this->flags);
$clone->options = array_merge($defaultOptions->options, $this->options);
return $clone;
}
public function __toString() : string
{
return $this->getOptionsString();
}
}