Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a takeout shell command #349

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,24 @@ takeout stop {container_id}
takeout stop {container_id1} {container_id2}
```

### Get a shell inside any Takeout container

To get a shell inside any container that is started with Takeout, you may run:

```bash
takeout shell {service}
```

Here are some examples:

```bash
takeout shell mysql
takeout shell neo4j
takeotu shell pgvector
tonysm marked this conversation as resolved.
Show resolved Hide resolved
```

This will reuse the running container. Takeout will start either a `bash` or a `sh` process inside the container, depending on what the container supports (this is automatically handled by Takeout).
tonysm marked this conversation as resolved.
Show resolved Hide resolved

## Running multiple versions of a dependency

Another of Takeout's benefits is that it allows you to have multiple versions of a dependency installed and running at the same time. That means, for example, that you can run both MySQL 5.7 and 8.0 at the same time, on different ports.
Expand Down
29 changes: 29 additions & 0 deletions app/Commands/ShellCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Commands;

use App\InitializesCommands;
use App\Services;
use Illuminate\Console\Command;

class ShellCommand extends Command
{
use InitializesCommands;

const MENU_TITLE = 'Get a shell inside a running Takeout container.';

protected $signature = 'shell {service}';

protected $description = 'Get a shell inside a running Takeout container.';

public function handle(Services $services): int
{
$this->initializecommand();

$service = $services->get($this->argument('service'));

resolve($service)->forwardShell();

return self::SUCCESS;
}
}
42 changes: 39 additions & 3 deletions app/Services/BaseService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Shell\Environment;
use App\Shell\Shell;
use App\WritesToConsole;
use Exception;
use Illuminate\Support\Str;
use Throwable;

Expand All @@ -15,14 +16,21 @@ abstract class BaseService
use WritesToConsole;

protected static $category;

protected static $displayName;

protected $organization = 'library'; // Official repositories use `library` as the organization name.

tonysm marked this conversation as resolved.
Show resolved Hide resolved
protected $imageName;

protected $dockerTagsClass = DockerTags::class;

protected $tag;

protected $dockerRunTemplate;

protected $defaultPort;

protected $defaultPrompts = [
[
'shortname' => 'port',
Expand All @@ -35,11 +43,17 @@ abstract class BaseService
'default' => 'latest',
],
];

protected $prompts = [];

protected $promptResponses = [];

protected $shell;

protected $environment;

protected $docker;

protected $useDefaults = false;

public function __construct(Shell $shell, Environment $environment, Docker $docker)
Expand Down Expand Up @@ -67,7 +81,7 @@ public static function name(): string
return static::$displayName ?? Str::afterLast(static::class, '\\');
}

public function enable(bool $useDefaults = false, array $passthroughOptions = [], string $runOptions = null): void
public function enable(bool $useDefaults = false, array $passthroughOptions = [], ?string $runOptions = null): void
{
$this->useDefaults = $useDefaults;

Expand All @@ -79,7 +93,7 @@ public function enable(bool $useDefaults = false, array $passthroughOptions = []

try {
$this->docker->bootContainer(
join(' ', array_filter([
implode(' ', array_filter([
$runOptions,
$this->sanitizeDockerRunTemplate($this->dockerRunTemplate),
$this->buildPassthroughOptionsString($passthroughOptions),
Expand All @@ -93,6 +107,28 @@ public function enable(bool $useDefaults = false, array $passthroughOptions = []
}
}

public function forwardShell(): void
{
if (! $this->docker->isDockerServiceRunning()) {
throw new Exception('Docker is not running.');
}

$service = $this->docker->takeoutContainers()->first(function ($container) {
return str_starts_with($container['names'], "TO--{$this->shortName()}--");
});

if (! $service) {
throw new Exception(sprintf('Service %s is not enabled.', $this->shortName()));
}

$this->docker->forwardShell($service['container_id'], $this->shellCommand());
}

protected function shellCommand(): string
{
return 'bash';
}

public function organization(): string
{
return $this->organization;
Expand Down Expand Up @@ -236,6 +272,6 @@ public function buildPassthroughOptionsString(array $passthroughOptions): string
return '';
}

return join(' ', $passthroughOptions);
return implode(' ', $passthroughOptions);
}
}
7 changes: 7 additions & 0 deletions app/Services/Beanstalkd.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ class Beanstalkd extends BaseService
protected static $category = Category::CACHE;

protected $organization = 'schickling';

protected $imageName = 'beanstalkd';

protected $defaultPort = 11300;

protected $dockerRunTemplate = '-p "${:port}":11300 \
"${:organization}"/"${:image_name}":"${:tag}"';

protected function shellCommand(): string
{
return 'sh';
}
}
10 changes: 10 additions & 0 deletions app/Services/Buggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ class Buggregator extends BaseService
protected static $category = Category::TOOLS;

protected $dockerTagsClass = GitHubDockerTags::class;

protected $organization = 'ghcr.io';

protected $imageName = 'buggregator/server';

protected $tag = 'latest';

protected $defaultPort = 8000;

protected $prompts = [
[
'shortname' => 'smtp_port',
Expand Down Expand Up @@ -42,4 +47,9 @@ class Buggregator extends BaseService
-p "${:monolog_port}":9913 \
--network-alias "${:network_alias}" \
"${:organization}"/"${:image_name}":"${:tag}"';

protected function shellCommand(): string
{
return 'sh';
}
}
14 changes: 14 additions & 0 deletions app/Services/CouchDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,31 @@ class CouchDB extends BaseService
protected static $category = Category::DATABASE;

protected $imageName = 'couchdb';

protected $defaultPort = 5984;

protected $prompts = [
[
'shortname' => 'volume',
'prompt' => 'What is the Docker volume name?',
'default' => 'couchdb_data',
],
[
'shortname' => 'user',
'prompt' => 'What is the CouchDB User?',
'default' => 'couchdb',
],
[
'shortname' => 'password',
'prompt' => 'What is the CouchDB Password?',
'default' => 'password',
],
];

protected $dockerRunTemplate = '-p "${:port}":5984 \
-v "${:volume}":/opt/couchdb/data \
-e COUCHDB_USER="${:user}" \
-e COUCHDB_PASSWORD="${:password}" \
"${:organization}"/"${:image_name}":"${:tag}"';

protected static $displayName = 'CouchDB';
Expand Down
8 changes: 5 additions & 3 deletions app/Services/EventStoreDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ class EventStoreDB extends BaseService
protected static $category = Category::DATABASE;

protected $organization = 'eventstore';

protected $imageName = 'eventstore';

protected $defaultPort = 1113;

protected $prompts = [
[
'shortname' => 'web_port',
Expand All @@ -25,7 +28,6 @@ class EventStoreDB extends BaseService
protected $dockerRunTemplate = '-p "${:port}":1113 \
-p "${:web_port}":2113 \
-v "${:volume}":/var/lib/eventstore \
"${:organization}"/"${:image_name}":"${:tag}" \
--insecure --run-projections=All \
--enable-external-tcp --enable-atom-pub-over-http';
"${:organization}"/"${:image_name}":latest \
--insecure --run-projections=All';
}
8 changes: 8 additions & 0 deletions app/Services/MailDev.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ class MailDev extends BaseService
protected static $category = Category::MAIL;

protected $organization = 'maildev';

protected $imageName = 'maildev';

protected $defaultPort = 1025;

protected $prompts = [
[
'shortname' => 'web_port',
Expand All @@ -20,4 +23,9 @@ class MailDev extends BaseService
protected $dockerRunTemplate = '-p "${:port}":1025 \
-p "${:web_port}":1080 \
"${:organization}"/"${:image_name}":"${:tag}"';

protected function shellCommand(): string
{
return 'sh';
}
}
8 changes: 8 additions & 0 deletions app/Services/MailHog.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ class MailHog extends BaseService
protected static $category = Category::MAIL;

protected $organization = 'mailhog';

protected $imageName = 'mailhog';

protected $defaultPort = 1025;

protected $prompts = [
[
'shortname' => 'web_port',
Expand All @@ -20,4 +23,9 @@ class MailHog extends BaseService
protected $dockerRunTemplate = '-p "${:port}":1025 \
-p "${:web_port}":8025 \
"${:organization}"/"${:image_name}":"${:tag}"';

protected function shellCommand(): string
{
return 'sh';
}
}
8 changes: 8 additions & 0 deletions app/Services/Mailpit.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ class Mailpit extends BaseService
protected static $category = Category::MAIL;

protected $organization = 'axllent';

protected $imageName = 'mailpit';

protected $defaultPort = 1025;

protected $prompts = [
[
'shortname' => 'web_port',
Expand All @@ -20,4 +23,9 @@ class Mailpit extends BaseService
protected $dockerRunTemplate = '-p "${:port}":1025 \
-p "${:web_port}":8025 \
"${:organization}"/"${:image_name}":"${:tag}"';

protected function shellCommand(): string
{
return 'sh';
}
}
8 changes: 8 additions & 0 deletions app/Services/MeiliSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ class MeiliSearch extends BaseService
protected static $category = Category::SEARCH;

protected $organization = 'getmeili';

protected $imageName = 'meilisearch';

protected $defaultPort = 7700;

protected $prompts = [
[
'shortname' => 'volume',
Expand All @@ -20,4 +23,9 @@ class MeiliSearch extends BaseService
protected $dockerRunTemplate = '-p "${:port}":7700 \
-v "${:volume}":/data.ms \
"${:organization}"/"${:image_name}":"${:tag}"';

protected function shellCommand(): string
{
return 'sh';
}
}
5 changes: 4 additions & 1 deletion app/Services/OpenSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ class OpenSearch extends BaseService
protected static $category = Category::SEARCH;

protected $organization = 'opensearchproject';

protected $imageName = 'opensearch';

protected $defaultPort = 9200;

protected $prompts = [
[
'shortname' => 'volume',
Expand All @@ -23,7 +26,7 @@ class OpenSearch extends BaseService
[
'shortname' => 'disable_security',
'prompt' => 'Disable security plugin (true or false)?',
'default' => 'false',
'default' => 'true',
],
];

Expand Down
10 changes: 10 additions & 0 deletions app/Services/Soketi.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ class Soketi extends BaseService
protected static $category = Category::SOCKET;

protected $dockerTagsClass = QuayDockerTags::class;

protected $organization = 'quay.io';

protected $imageName = 'soketi/soketi';

protected $tag = 'latest-16-alpine';

protected $defaultPort = 6001;

protected $prompts = [
[
'shortname' => 'metrics_port',
Expand All @@ -41,4 +46,9 @@ public function __construct(Shell $shell, Environment $environment, Docker $dock
return $prompt;
}, $this->defaultPrompts);
}

protected function shellCommand(): string
{
return 'sh';
}
}
Loading
Loading