From d91225375883a85fa6fddccc9ac00103e1d32eac Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Wed, 28 Apr 2021 13:57:52 +0200 Subject: Reconnects after ssh timeout --- composer.json | 6 +-- composer.lock | 10 ++--- src/Command/RunCommand.php | 13 +++++-- src/Connection.php | 60 +++++++++++++++++++++-------- src/Module/ModuleInterface.php | 4 +- src/Support/SingletonTraitWithArguments.php | 25 ------------ 6 files changed, 60 insertions(+), 58 deletions(-) delete mode 100644 src/Support/SingletonTraitWithArguments.php diff --git a/composer.json b/composer.json index f850f87..806a885 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,6 @@ ], "require": { "php": "^8.0", - "petrknap/php-singleton": "^1.0", "php-iac/modules": "*", "php-iac/role": "*", "phpseclib/phpseclib": "^3.0", @@ -34,8 +33,5 @@ "minimum-stability": "dev", "bin": [ "bin/phpiac" - ], - "scripts": { - "compile": "@php -dphar.readonly=0 bin/compile" - } + ] } diff --git a/composer.lock b/composer.lock index 6f79623..e302ffa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "285150783eb4290e52f7b0565a82c352", + "content-hash": "f42e6d4c03cd28c00fbb8f8b4206c7b5", "packages": [ { "name": "paragonie/constant_time_encoding", @@ -174,7 +174,7 @@ "dist": { "type": "path", "url": "../modules", - "reference": "d4d5ae3bb6566311b2d42cf888e463b62f6cf0dc" + "reference": "11dc8c730dda2c5bd38cb386f96331c5ce3cac9c" }, "require": { "php": "^8.0", @@ -205,7 +205,7 @@ "dist": { "type": "path", "url": "../role", - "reference": "a8ddac7859f7139ce13d244c7dd39fae6ed07db0" + "reference": "1caef9750cff776cadc3ee225ade458045d17c0b" }, "require": { "php": "^8.0" @@ -339,7 +339,7 @@ "type": "tidelift" } ], - "time": "2021-04-19T03:20:48+00:00" + "time": "2021-04-26T14:07:55+00:00" }, { "name": "psr/container", @@ -882,7 +882,7 @@ "type": "tidelift" } ], - "time": "2021-04-19T09:32:22+00:00" + "time": "2021-04-23T08:04:02+00:00" }, { "name": "symfony/polyfill-php73", diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php index cc9c7fd..e76c063 100644 --- a/src/Command/RunCommand.php +++ b/src/Command/RunCommand.php @@ -5,6 +5,7 @@ namespace PHPIAC\Command; use PHPIAC\Connection; use PHPIAC\Task; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -28,21 +29,25 @@ class RunCommand extends Command { $config = include $input->getOption('config'); - Connection::getInstance($config['host'], $config['user'], $config['private_key_file']); + Connection::initialize($config['host'], $config['user'], $config['private_key_file']); + + /**@var FormatterHelper $formater*/ + $formater = $this->getHelper('formatter'); foreach ($config['tasks'] as $task) { /**@var Task $task*/ + $output->writeln($task->getName()); if (! $task->module->checkState()) { - $output->writeln($task->getName()); $output->writeln('Running'); - $task->module->getCommands(); + $task->module->execute(); } else { - $output->writeln($task->getName()); $output->writeln('Skipping'); } + + $output->writeln('- - -'); } return Command::SUCCESS; diff --git a/src/Connection.php b/src/Connection.php index 2052cd1..2cddeb4 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -2,7 +2,6 @@ namespace PHPIAC; -use PHPIAC\Support\SingletonTraitWithArguments; use phpseclib3\Crypt\PublicKeyLoader; use phpseclib3\Net\SFTP; use phpseclib3\Net\SSH2; @@ -12,39 +11,64 @@ use phpseclib3\Net\SSH2; * * @method static string exec(string $command, callback $callback = null) * @method static string|bool|null read(string $expect = '', int $read = 1) + * @method static bool write(string $cmd) * @method static enablePty() * @method static disablePty() */ class Connection { - use SingletonTraitWithArguments; + private static SSH2 $ssh; + private static SFTP $sftp; - private SSH2 $ssh; - private SFTP $sftp; + private static string $host; + private static string $user; + private static mixed $key; /** * Connection constructor. * * @param string $host * @param string $user - * @param string $key + * @param string $keyFile * * @throws \Exception */ - public function __construct(string $host, string $user, string $key) + public static function initialize(string $host, string $user, string $keyFile) { - $this->ssh = new SSH2($host); - $key = PublicKeyLoader::load(file_get_contents($key)); - if (! $this->ssh->login($user, $key)) { + self::$host = $host; + self::$user = $user; + self::$key = PublicKeyLoader::load(file_get_contents($keyFile)); + + self::connect(); + } + + /** + * @throws \Exception + */ + private static function connect() + { + self::$ssh = new SSH2(self::$host); + if (! self::$ssh->login(self::$user, self::$key)) { throw new \Exception('SSH Login failed'); } - $this->sftp = new SFTP($host); - if (! $this->sftp->login($user, $key)) { + self::$sftp = new SFTP(self::$host); + if (! self::$sftp->login(self::$user, self::$key)) { throw new \Exception('SFTP Login failed'); } } + /** + * @throws \Exception + */ + private static function ensureConnection() + { + if (! self::$ssh->isConnected() || + ! self::$sftp->isConnected()) { + self::connect(); + } + } + /** * Calls SSH2 methods statically * @@ -55,13 +79,13 @@ class Connection */ public static function __callStatic(string $name, array $arguments): mixed { - $self = self::getInstance(); + self::ensureConnection(); - if (! method_exists($self->ssh, $name)) { - return $self->sftp->$name(...$arguments); + if (! method_exists(self::$ssh, $name)) { + return self::$sftp->$name(...$arguments); } - return $self->ssh->$name(...$arguments); + return self::$ssh->$name(...$arguments); } /** @@ -69,10 +93,12 @@ class Connection */ public static function put($remote_file, $data, $mode = SFTP::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null): bool { + self::ensureConnection(); + $tmp = bin2hex(random_bytes(10)); # work around sftp sudo put restrictions return - self::getInstance()->sftp->put("/tmp/$tmp", $data, $mode, $start, $local_start, $progressCallback) && - self::getInstance()->ssh->exec("sudo mv /tmp/$tmp $remote_file"); + self::$sftp->put("/tmp/$tmp", $data, $mode, $start, $local_start, $progressCallback) && + self::$ssh->exec("sudo mv /tmp/$tmp $remote_file"); } } diff --git a/src/Module/ModuleInterface.php b/src/Module/ModuleInterface.php index 649a095..0a12dfc 100644 --- a/src/Module/ModuleInterface.php +++ b/src/Module/ModuleInterface.php @@ -10,7 +10,7 @@ interface ModuleInterface public function checkState(): bool; /** - * @return array + * @return void */ - public function getCommands(): array; + public function execute(): void; } diff --git a/src/Support/SingletonTraitWithArguments.php b/src/Support/SingletonTraitWithArguments.php deleted file mode 100644 index 2ac0653..0000000 --- a/src/Support/SingletonTraitWithArguments.php +++ /dev/null @@ -1,25 +0,0 @@ -