diff --git a/README.md b/README.md index 660f124..a4431ee 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,46 @@ $result = Process::ssh([ ->run('ls -al'); ``` +### Use the favorites method provided by Laravel's Process class. + +For more information, refer to the official documentation : https://laravel.com/docs/11.x/processes + +```php +$process = Process::ssh([ + 'host' => '192.168.1.10', + 'user' => 'username', + 'password' => 'your_password', + ]) + ->start('bash import.sh'); + +$result = $process->wait(); + +``` + +```php +[$result1, $result2] = Process::ssh([ + 'host' => '192.168.1.10', + 'user' => 'username', + 'password' => 'your_password', + ]) + ->concurrently(function (Pool $pool) { + $pool->command('ls -al'); + $pool->command('whoami'); + }); +``` + +```php +$result = Process::ssh([ + 'host' => '192.168.1.10', + 'user' => 'username', + 'password' => 'your_password', + ]) + ->pool(function (Pool $pool) { + $pool->command('ls -al'); + $pool->command('whoami'); + }); +``` + ### SSH multiplexing If you want to execute multiple commands over the same SSH connection, SSH multiplexing allows you to reuse an existing TCP connection, improving efficiency and reducing overhead. diff --git a/src/PendingProcess.php b/src/PendingProcess.php index f36f8da..2f0982f 100644 --- a/src/PendingProcess.php +++ b/src/PendingProcess.php @@ -21,6 +21,18 @@ class PendingProcess extends BasePendingProcess private bool $handleSsh = false; + /** + * Override the command string to handle SSH commands. + */ + public function command(array|string $command) + { + $command = $this->buildCommand($command); + + $this->command = $command; + + return $this; + } + /** * Set configuration for the SSH connection. */ @@ -60,6 +72,10 @@ public function setConfig(array $config, bool $handleSsh) */ public function buildCommand(array|string|null $command): array|string|null { + if (! $command) { + return $command; + } + if (! $this->handleSsh) { return $command; } @@ -161,6 +177,8 @@ protected function toSymfonyProcess(array|string|null $command) { $command = $this->buildCommand($command); - return parent::toSymfonyProcess($command); + $process = parent::toSymfonyProcess($command); + + return $process; } } diff --git a/src/ProcessSsh.php b/src/ProcessSsh.php index 353aa7e..c4f96f5 100644 --- a/src/ProcessSsh.php +++ b/src/ProcessSsh.php @@ -61,15 +61,6 @@ public function addExtraOption(string $option): self return $this; } - public function pool(callable $callback) - { - if ($this->handleSsh) { - throw new \InvalidArgumentException('Cannot pool processes with SSH enabled.'); - } - - return parent::pool($callback); - } - public function pipe(callable|array $callback, ?callable $output = null) { if ($this->handleSsh) { @@ -79,16 +70,6 @@ public function pipe(callable|array $callback, ?callable $output = null) return parent::pipe($callback, $output); } - public function concurrently(callable $callback, ?callable $output = null) - { - - if ($this->handleSsh) { - throw new \InvalidArgumentException('Cannot concurrently processes with SSH enabled.'); - } - - return parent::concurrently($callback, $output); - } - /** * Create a new pending process instance. */ diff --git a/tests/ProcessSshTest.php b/tests/ProcessSshTest.php index d7da6bb..00b9e84 100644 --- a/tests/ProcessSshTest.php +++ b/tests/ProcessSshTest.php @@ -3,16 +3,23 @@ use Bagel\ProcessSsh\PendingProcess; use Bagel\ProcessSsh\Providers\ProcessSshServiceProvider; use Illuminate\Process\FakeProcessResult; +use Illuminate\Process\Pool; use Illuminate\Support\Facades\Process; use Orchestra\Testbench\TestCase; uses(TestCase::class)->beforeEach(function () { $this->app->register(ProcessSshServiceProvider::class); + + $this->basicSshConfig = [ + 'host' => '192.178.0.1', + 'user' => 'ubuntu', + 'port' => 22, + ]; }); it('process config set', function () { $process = Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', 'user' => 'ubuntu', 'port' => 22, 'extraOptions' => [ @@ -22,7 +29,7 @@ 'private_key' => '/path/to/key', ]); - expect($process->sshConfig()['host'])->toBe('example.com'); + expect($process->sshConfig()['host'])->toBe('192.178.0.1'); expect($process->sshConfig()['user'])->toBe('ubuntu'); expect($process->sshConfig()['port'])->toBe(22); expect($process->sshConfig()['extraOptions'])->toBe([ @@ -34,7 +41,7 @@ it('process add extra options', function () { $process = Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', 'user' => 'ubuntu', 'port' => 22, ])->addExtraOption('-o StrictHostKeyChecking=no'); @@ -46,7 +53,7 @@ it('process disableStrictHostKeyChecking', function () { $process = Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', 'user' => 'ubuntu', 'port' => 22, ])->disableStrictHostKeyChecking(); @@ -87,12 +94,12 @@ Process::fake(); $process = Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', ]) ->disableStrictHostKeyChecking() ->run('ls -al'); - expect($process->command())->toBe("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null example.com 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); + expect($process->command())->toBe("ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 192.178.0.1 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); Process::assertRan('ls -al'); }); @@ -101,7 +108,7 @@ Process::fake(); $process = Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', 'user' => 'ubuntu', 'password' => 'password', 'port' => 22, @@ -113,7 +120,7 @@ ->disableStrictHostKeyChecking() ->run('ls -al'); - expect($process->command())->toBe("sshpass -p 'password' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@example.com 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); + expect($process->command())->toBe("sshpass -p 'password' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@192.178.0.1 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); Process::assertRan('ls -al'); }); @@ -122,7 +129,7 @@ Process::fake(); $process = Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', 'user' => 'ubuntu', 'port' => 22, 'private_key' => '/path/to/key', @@ -130,29 +137,11 @@ ->disableStrictHostKeyChecking() ->run('ls -al'); - expect($process->command())->toBe("ssh -i /path/to/key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@example.com 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); + expect($process->command())->toBe("ssh -i /path/to/key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@192.178.0.1 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); Process::assertRan('ls -al'); }); -it('exception thrown process run with array', function () { - Process::fake(); - - Process::ssh([ - 'host' => '127.0.0.1', - ])->run(['ls', '-al']); - -})->throws(InvalidArgumentException::class, 'Array commands are not supported for SSH connections'); - -it('exception thrown process start with array', function () { - Process::fake(); - - Process::ssh([ - 'host' => '127.0.0.1', - ])->start(['ls', '-al']); - -})->throws(InvalidArgumentException::class, 'Array commands are not supported for SSH connections'); - it('Process can run normaly', function () { Process::fake(); @@ -183,7 +172,7 @@ Process::fake(); Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', 'user' => 'ubuntu', 'password' => 'password', 'port' => 22, @@ -202,7 +191,7 @@ Process::fake(); Process::ssh([ - 'host' => 'example.com', + 'host' => '192.178.0.1', 'user' => 'ubuntu', 'password' => 'password', 'port' => 22, @@ -217,60 +206,87 @@ }); }); -it('can\'t pool processes with SSH enabled', function () { +it('invoke process::concurrently', function () { Process::fake(); - Process::ssh([ - 'host' => 'example.com', - 'user' => 'ubuntu', - 'password' => 'password', - 'port' => 22, - ])->pool(function () { - // + $process = Process::concurrently(function (Pool $pool) { + $pool->command('ls -al'); + $pool->command('whoami'); }); -})->throws(InvalidArgumentException::class, 'Cannot pool processes with SSH enabled.'); + expect($process[0]->command())->toBe('ls -al'); + expect($process[1]->command())->toBe('whoami'); + + Process::assertRan('ls -al'); + Process::assertRan('whoami'); +}); -it('can\'t pipe processes with SSH enabled', function () { +it('invoke process::concurrently ssh', function () { Process::fake(); - Process::ssh([ - 'host' => 'example.com', - 'user' => 'ubuntu', - 'password' => 'password', - 'port' => 22, - ])->pipe(function () { - // + $process = Process::ssh($this->basicSshConfig)->concurrently(function (Pool $pool) { + $pool->command('ls -al'); + $pool->command('whoami'); }); -})->throws(InvalidArgumentException::class, 'Cannot pipe processes with SSH enabled.'); + expect($process[0]->command())->toBe("ssh ubuntu@192.178.0.1 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); + expect($process[1]->command())->toBe("ssh ubuntu@192.178.0.1 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'whoami'.PHP_EOL.'EOF-PROCESS-SSH'); + +}); -it('can\'t concurrently processes with SSH enabled', function () { +it('invoke process::pool', function () { Process::fake(); - Process::ssh([ - 'host' => 'example.com', - 'user' => 'ubuntu', - 'password' => 'password', - 'port' => 22, - ])->concurrently(function () { - // + $process = Process::pool(function (Pool $pool) { + $pool->command('ls -al'); + $pool->command('whoami'); + }); + + $results = $process->wait(); + expect($results[0]->command())->toBe('ls -al'); + expect($results[1]->command())->toBe('whoami'); + + Process::assertRan('ls -al'); + Process::assertRan('whoami'); +}); + +it('invoke process::pool ssh', function () { + Process::fake(); + + $process = Process::ssh($this->basicSshConfig)->pool(function (Pool $pool) { + $pool->command('ls -al'); + $pool->command('whoami'); }); -})->throws(InvalidArgumentException::class, 'Cannot concurrently processes with SSH enabled.'); + $results = $process->wait(); + expect($results[0]->command())->toBe("ssh ubuntu@192.178.0.1 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'ls -al'.PHP_EOL.'EOF-PROCESS-SSH'); + expect($results[1]->command())->toBe("ssh ubuntu@192.178.0.1 'bash -se' << \EOF-PROCESS-SSH".PHP_EOL.'whoami'.PHP_EOL.'EOF-PROCESS-SSH'); + +}); + +it('exception thrown process run with array', function () { + Process::fake(); + + Process::ssh([ + 'host' => '127.0.0.1', + ])->run(['ls', '-al']); + +})->throws(InvalidArgumentException::class, 'Array commands are not supported for SSH connections.'); + +it('exception thrown process start with array', function () { + Process::fake(); -// it('timeout process', function () { -// //Process::fake(); + Process::ssh([ + 'host' => '127.0.0.1', + ])->start(['ls', '-al']); -// $process = Process::ssh([ -// 'host' => '192.168.8.5', -// 'user' => 'ubuntu', -// //'password' => 'password', -// 'port' => 22, -// ]) -// ->run('ls'); +})->throws(InvalidArgumentException::class, 'Array commands are not supported for SSH connections.'); -// dump($process->errorOutput()); -// dump($process->output()); +it('invoke process::pipe', function () { + Process::fake(); -// })->only(); + $process = Process::ssh($this->basicSshConfig)->pipe([ + 'ls -al', + 'whoami', + ]); +})->throws(InvalidArgumentException::class, 'Cannot pipe processes with SSH enabled.');