Skip to content

Commit fbc9a3d

Browse files
authored
Merge pull request #349 from tighten/tm/shell-cmd
Add a `takeout shell` command
2 parents a39e947 + ca988dc commit fbc9a3d

16 files changed

+138
-9
lines changed

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,24 @@ takeout stop {container_id}
169169
takeout stop {container_id1} {container_id2}
170170
```
171171

172+
### Get a shell inside any Takeout container
173+
174+
To get a shell inside any container that is started with Takeout, you may run:
175+
176+
```bash
177+
takeout shell {service}
178+
```
179+
180+
Here are some examples:
181+
182+
```bash
183+
takeout shell mysql
184+
takeout shell neo4j
185+
takeout shell pgvector
186+
```
187+
188+
This will open a shell inside the running container for the service you provide. Takeout will start either a `bash` or a `sh` process inside the container, depending on what the container supports.
189+
172190
## Running multiple versions of a dependency
173191

174192
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.

app/Commands/ShellCommand.php

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Commands;
4+
5+
use App\InitializesCommands;
6+
use App\Services;
7+
use Illuminate\Console\Command;
8+
9+
class ShellCommand extends Command
10+
{
11+
use InitializesCommands;
12+
13+
const MENU_TITLE = 'Get a shell inside a running Takeout container.';
14+
15+
protected $signature = 'shell {service}';
16+
protected $description = 'Get a shell inside a running Takeout container.';
17+
18+
public function handle(Services $services): int
19+
{
20+
$this->initializecommand();
21+
22+
$service = $services->get($this->argument('service'));
23+
24+
resolve($service)->forwardShell();
25+
26+
return self::SUCCESS;
27+
}
28+
}

app/Services/BaseService.php

+23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use App\Shell\Environment;
88
use App\Shell\Shell;
99
use App\WritesToConsole;
10+
use Exception;
1011
use Illuminate\Support\Str;
1112
use Throwable;
1213

@@ -93,6 +94,28 @@ public function enable(bool $useDefaults = false, array $passthroughOptions = []
9394
}
9495
}
9596

97+
public function forwardShell(): void
98+
{
99+
if (! $this->docker->isDockerServiceRunning()) {
100+
throw new Exception('Docker is not running.');
101+
}
102+
103+
$service = $this->docker->takeoutContainers()->first(function ($container) {
104+
return str_starts_with($container['names'], "TO--{$this->shortName()}--");
105+
});
106+
107+
if (! $service) {
108+
throw new Exception(sprintf('Service %s is not enabled.', $this->shortName()));
109+
}
110+
111+
$this->docker->forwardShell($service['container_id'], $this->shellCommand());
112+
}
113+
114+
protected function shellCommand(): string
115+
{
116+
return 'bash';
117+
}
118+
96119
public function organization(): string
97120
{
98121
return $this->organization;

app/Services/Beanstalkd.php

+5
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,9 @@ class Beanstalkd extends BaseService
1212

1313
protected $dockerRunTemplate = '-p "${:port}":11300 \
1414
"${:organization}"/"${:image_name}":"${:tag}"';
15+
16+
protected function shellCommand(): string
17+
{
18+
return 'sh';
19+
}
1520
}

app/Services/Buggregator.php

+5
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,9 @@ class Buggregator extends BaseService
4242
-p "${:monolog_port}":9913 \
4343
--network-alias "${:network_alias}" \
4444
"${:organization}"/"${:image_name}":"${:tag}"';
45+
46+
protected function shellCommand(): string
47+
{
48+
return 'sh';
49+
}
4550
}

app/Services/CouchDB.php

+12
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,22 @@ class CouchDB extends BaseService
1414
'prompt' => 'What is the Docker volume name?',
1515
'default' => 'couchdb_data',
1616
],
17+
[
18+
'shortname' => 'user',
19+
'prompt' => 'What is the CouchDB User?',
20+
'default' => 'couchdb',
21+
],
22+
[
23+
'shortname' => 'password',
24+
'prompt' => 'What is the CouchDB Password?',
25+
'default' => 'password',
26+
],
1727
];
1828

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

2335
protected static $displayName = 'CouchDB';

app/Services/EventStoreDB.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class EventStoreDB extends BaseService
2525
protected $dockerRunTemplate = '-p "${:port}":1113 \
2626
-p "${:web_port}":2113 \
2727
-v "${:volume}":/var/lib/eventstore \
28-
"${:organization}"/"${:image_name}":"${:tag}" \
29-
--insecure --run-projections=All \
30-
--enable-external-tcp --enable-atom-pub-over-http';
28+
"${:organization}"/"${:image_name}":latest \
29+
--insecure --run-projections=All';
3130
}

app/Services/MailDev.php

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ class MailDev extends BaseService
2020
protected $dockerRunTemplate = '-p "${:port}":1025 \
2121
-p "${:web_port}":1080 \
2222
"${:organization}"/"${:image_name}":"${:tag}"';
23+
24+
protected function shellCommand(): string
25+
{
26+
return 'sh';
27+
}
2328
}

app/Services/MailHog.php

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ class MailHog extends BaseService
2020
protected $dockerRunTemplate = '-p "${:port}":1025 \
2121
-p "${:web_port}":8025 \
2222
"${:organization}"/"${:image_name}":"${:tag}"';
23+
24+
protected function shellCommand(): string
25+
{
26+
return 'sh';
27+
}
2328
}

app/Services/Mailpit.php

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ class Mailpit extends BaseService
2020
protected $dockerRunTemplate = '-p "${:port}":1025 \
2121
-p "${:web_port}":8025 \
2222
"${:organization}"/"${:image_name}":"${:tag}"';
23+
24+
protected function shellCommand(): string
25+
{
26+
return 'sh';
27+
}
2328
}

app/Services/MeiliSearch.php

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ class MeiliSearch extends BaseService
2020
protected $dockerRunTemplate = '-p "${:port}":7700 \
2121
-v "${:volume}":/data.ms \
2222
"${:organization}"/"${:image_name}":"${:tag}"';
23+
24+
protected function shellCommand(): string
25+
{
26+
return 'sh';
27+
}
2328
}

app/Services/OpenSearch.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class OpenSearch extends BaseService
2323
[
2424
'shortname' => 'disable_security',
2525
'prompt' => 'Disable security plugin (true or false)?',
26-
'default' => 'false',
26+
'default' => 'true',
2727
],
2828
];
2929

app/Services/Soketi.php

+5
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,9 @@ public function __construct(Shell $shell, Environment $environment, Docker $dock
4141
return $prompt;
4242
}, $this->defaultPrompts);
4343
}
44+
45+
protected function shellCommand(): string
46+
{
47+
return 'sh';
48+
}
4449
}

app/Services/Traefik.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,8 @@ class Traefik extends BaseService
1212
protected static $category = Category::TOOLS;
1313

1414
protected $imageName = 'traefik';
15-
1615
protected $defaultTag = 'v2.10';
17-
1816
protected $defaultPort = 8080;
19-
2017
protected $prompts = [
2118
[
2219
'shortname' => 'config_dir',
@@ -64,6 +61,11 @@ public function __construct(Shell $shell, Environment $environment, Docker $dock
6461
}, $this->prompts);
6562
}
6663

64+
protected function shellCommand(): string
65+
{
66+
return 'sh';
67+
}
68+
6769
protected function prompts(): void
6870
{
6971
parent::prompts();

app/Shell/Docker.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace App\Shell;
44

55
use App\Exceptions\DockerContainerMissingException;
6-
use App\Shell\Environment;
76
use Exception;
87
use Illuminate\Support\Collection;
98
use Illuminate\Support\Str;
@@ -200,6 +199,19 @@ public function stopDockerService(): void
200199
}
201200
}
202201

202+
public function forwardShell(string $containerId, string $shellCommand): void
203+
{
204+
$command = $this->shell->buildProcess(sprintf(
205+
'docker exec -it "%s" %s',
206+
$containerId,
207+
$shellCommand,
208+
));
209+
210+
$command->setTty(true);
211+
$command->setTimeout(null);
212+
$command->run();
213+
}
214+
203215
protected function runAndParseTable(string $command): Collection
204216
{
205217
return $this->formatter->rawTableOutputToCollection(

tests/Feature/DockerTagsTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function it_sorts_the_versions_naturally()
4242
$tags = collect($dockerTags->getTags());
4343

4444
$this->assertEquals('latest', $tags->shift());
45-
$this->assertEquals('16.3', $tags->shift());
45+
$this->assertEquals('17.0', $tags->shift());
4646
}
4747

4848
/** @test */

0 commit comments

Comments
 (0)