Skip to content

Commit

Permalink
Implement a new kubectl transport (#60)
Browse files Browse the repository at this point in the history
* Implement a new kubectl transport for accessing Drupal instances running in Kubernetes.

* Add tests for kubectl transport.

* Update CHANGELOG.md

* Do not escape arguments after "--"

* PHPCS Beautify
  • Loading branch information
rudolfbyker authored Feb 19, 2022
1 parent ca41dc8 commit 8f371ef
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
28 changes: 28 additions & 0 deletions src/Factory/KubectlTransportFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Consolidation\SiteProcess\Factory;

use Consolidation\SiteAlias\SiteAliasInterface;
use Consolidation\SiteProcess\Transport\KubectlTransport;

/**
* KubectlTransportFactory will create an KubectlTransport for applicable site aliases.
*/
class KubectlTransportFactory implements TransportFactoryInterface
{
/**
* @inheritdoc
*/
public function check(SiteAliasInterface $siteAlias)
{
return $siteAlias->has('kubectl');
}

/**
* @inheritdoc
*/
public function create(SiteAliasInterface $siteAlias)
{
return new KubectlTransport($siteAlias);
}
}
2 changes: 2 additions & 0 deletions src/ProcessManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());

Expand Down
76 changes: 76 additions & 0 deletions src/Transport/KubectlTransport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Consolidation\SiteProcess\Transport;

use Consolidation\SiteProcess\SiteProcess;
use Consolidation\SiteAlias\SiteAliasInterface;
use Consolidation\SiteProcess\Util\Shell;

/**
* KubectlTransport knows how to wrap a command such that it runs in a container
* on Kubernetes via kubectl.
*/
class KubectlTransport implements TransportInterface
{
/** @var bool */
protected $tty;

/** @var \Consolidation\SiteAlias\SiteAliasInterface */
protected $siteAlias;

public function __construct(SiteAliasInterface $siteAlias)
{
$this->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
);
}
}
4 changes: 2 additions & 2 deletions src/Transport/TransportInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
68 changes: 68 additions & 0 deletions tests/Transport/KubectlTransportTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Consolidation\SiteProcess;

use Consolidation\SiteProcess\Transport\KubectlTransport;
use PHPUnit\Framework\TestCase;
use Consolidation\SiteAlias\SiteAlias;

class KubectlTransportTest extends TestCase
{
/**
* Data provider for testWrap.
*/
public function wrapTestValues()
{
return [
// Everything explicit.
[
'kubectl --namespace=vv exec --tty=false --stdin=false deploy/drupal --container=drupal -- ls',
['ls'],
[
'kubectl' => [
'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));
}
}

0 comments on commit 8f371ef

Please sign in to comment.