diff --git a/CHANGELOG.md b/CHANGELOG.md index 9018813..90a021a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### Unreleased + +* Support kubectl transport (#60) + ### 4.1.3 / 4.1.2 - 2022/Jan/18 * Support symfony/process ^5 via illicit access to a private member (#58) diff --git a/src/Factory/KubectlTransportFactory.php b/src/Factory/KubectlTransportFactory.php new file mode 100644 index 0000000..dcfc651 --- /dev/null +++ b/src/Factory/KubectlTransportFactory.php @@ -0,0 +1,28 @@ +has('kubectl'); + } + + /** + * @inheritdoc + */ + public function create(SiteAliasInterface $siteAlias) + { + return new KubectlTransport($siteAlias); + } +} diff --git a/src/ProcessManager.php b/src/ProcessManager.php index 7e94557..ce9c5ba 100644 --- a/src/ProcessManager.php +++ b/src/ProcessManager.php @@ -2,6 +2,7 @@ namespace Consolidation\SiteProcess; +use Consolidation\SiteProcess\Factory\KubectlTransportFactory; use Consolidation\SiteProcess\Factory\VagrantTransportFactory; use Psr\Log\LoggerInterface; use Consolidation\SiteAlias\SiteAliasInterface; @@ -68,6 +69,7 @@ public static function createDefault() public static function addTransports(ProcessManager $processManager) { $processManager->add(new SshTransportFactory()); + $processManager->add(new KubectlTransportFactory()); $processManager->add(new DockerComposeTransportFactory()); $processManager->add(new VagrantTransportFactory()); diff --git a/src/Transport/KubectlTransport.php b/src/Transport/KubectlTransport.php new file mode 100644 index 0000000..2ee797d --- /dev/null +++ b/src/Transport/KubectlTransport.php @@ -0,0 +1,76 @@ +siteAlias = $siteAlias; + } + + /** + * @inheritdoc + */ + public function configure(SiteProcess $process) + { + $this->tty = $process->isTty(); + } + + /** + * inheritdoc + */ + public function wrap($args) + { + # TODO: How/where do we complain if a required argument is not available? + $namespace = $this->siteAlias->get('kubectl.namespace'); + $tty = $this->tty && $this->siteAlias->get('kubectl.tty', false) ? "true" : "false"; + $interactive = $this->tty && $this->siteAlias->get('kubectl.interactive', false) ? "true" : "false"; + $resource = $this->siteAlias->get('kubectl.resource'); + $container = $this->siteAlias->get('kubectl.container'); + + $transport = [ + 'kubectl', + "--namespace=$namespace", + 'exec', + "--tty=$tty", + "--stdin=$interactive", + $resource, + ]; + if ($container) { + $transport[] = "--container=$container"; + } + $transport[] = "--"; + + return array_merge($transport, $args); + } + + /** + * @inheritdoc + */ + public function addChdir($cd_remote, $args) + { + return array_merge( + [ + 'cd', + $cd_remote, + Shell::op('&&'), + ], + $args + ); + } +} diff --git a/src/Transport/TransportInterface.php b/src/Transport/TransportInterface.php index 77c7bc6..a707973 100644 --- a/src/Transport/TransportInterface.php +++ b/src/Transport/TransportInterface.php @@ -5,8 +5,8 @@ use Consolidation\SiteProcess\SiteProcess; /** - * SshTransport knows how to wrap a command such that it runs on a remote - * system via the ssh cli. + * Transports know how to wrap a command such that it runs on a remote system + * via some other command. * * There is always a transport for every factory, and visa-versa. * diff --git a/tests/Transport/KubectlTransportTest.php b/tests/Transport/KubectlTransportTest.php new file mode 100644 index 0000000..af4f889 --- /dev/null +++ b/tests/Transport/KubectlTransportTest.php @@ -0,0 +1,68 @@ + [ + 'tty' => false, + 'interactive' => false, + 'namespace' => 'vv', + 'resource' => 'deploy/drupal', + 'container' => 'drupal', + ] + ], + ], + + // Minimal. Kubectl will pick a container. + [ + 'kubectl --namespace=vv exec --tty=false --stdin=false deploy/drupal -- ls', + ['ls'], + [ + 'kubectl' => [ + 'namespace' => 'vv', + 'resource' => 'deploy/drupal', + ] + ], + ], + + // Don't escape arguments after "--" + [ + 'kubectl --namespace=vv exec --tty=false --stdin=false deploy/drupal -- asdf "double" \'single\'', + ['asdf', '"double"', "'single'"], + [ + 'kubectl' => [ + 'namespace' => 'vv', + 'resource' => 'deploy/drupal', + ] + ], + ], + ]; + } + + /** + * @dataProvider wrapTestValues + */ + public function testWrap($expected, $args, $siteAliasData) + { + $siteAlias = new SiteAlias($siteAliasData, '@alias.dev'); + $dockerTransport = new KubectlTransport($siteAlias); + $actual = $dockerTransport->wrap($args); + $this->assertEquals($expected, implode(' ', $actual)); + } +}