Skip to content

Commit

Permalink
Merge pull request #4 from idrislab/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
luispittagros authored Dec 5, 2016
2 parents f2d3e31 + fe4e1a4 commit a8d2d09
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 93 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"email": "[email protected]"
}
],
"keywords": ["laravel", "docker", "services"],
"keywords": ["laravel", "docker", "containers", "automate"],
"license": "MIT",
"require": {
"php": ">=5.6.4",
Expand Down
252 changes: 160 additions & 92 deletions src/DockerContainers.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,22 @@ class DockerContainers extends Command
* @var Docker
*/
protected $docker;
/**
* @var array
*/
protected $attributes;
/**
* @var array
*/
protected $network = [];
/**
* @var array
*/
protected $instances;
/**
* @var array
*/
protected $container;

/**
* Create a new command instance.
Expand All @@ -92,27 +107,37 @@ public function handle()
collect(explode(",", $containers))
->mapWithKeys(function ($container) {
//Retrieve only current container attributes
$containers = collect($this->containers)->map(function ($attributes, $current) use (&$container) {
if (strtolower($current) === strtolower($container)) {
$container = $current;

return $attributes;
}
})->only($container);
$containers = collect($this->containers)
->map(function ($attributes, $current) use (&$container) {
if ($this->option('name') === null) {
if (strtolower($current) === strtolower($container)) {
$container = $current;

return $attributes;
}
} elseif (strtolower($this->option('name')) === strtolower($current)) {
$container = $current;

return $attributes;
}
})
->only($container);

return $containers;
})
->each(function ($attributes, $container) {

$this->prepare($container, $attributes);

switch ($this->argument('option')) {
case "start":
$this->startContainer($container, $attributes);
$this->start();
break;
case 'stop':
return $this->stopContainer($container, $attributes);
return $this->stop();
break;
case 'restart':
$this->restartContainer($container, $attributes);
$this->restart();
break;
default:
}
Expand All @@ -122,6 +147,8 @@ public function handle()
}

/**
* Add containers
*
* @param array $containers
*/
protected function addContainers(array $containers)
Expand All @@ -130,116 +157,81 @@ protected function addContainers(array $containers)
}

/**
* @param string $container
* @param array $attributes
* Start docker container
*/
private function startContainer($container, array $attributes)
private function start()
{
$tag = $attributes['repo'].':'.$attributes['tag'];
if (!$this->docker->imageExists($tag)) {
$this->docker->pull($tag);
}
$this->pullImage();

$instances = $this->getContainerInstances($container, $attributes);
foreach ($this->instances as $container) {
$this->container = $container;

foreach ($instances as $instance) {
if ($this->docker->isNamedContainerRunning($instance['name'])) {
if (!$this->confirm("$container is already running, do you want restart?")) {
continue;
if ($this->docker->isNamedContainerRunning($container['name'])) {
if ($this->confirm("{$container['name']} is already running, do you want restart?")) {
$this->restart();
}

$this->restartContainer($instance, $attributes);
break;
continue;
}

$this->runContainer($instance, $attributes);
$this->runContainer();
}
}

/**
* @param array $container
* @param array $attributes
*
* @throws Exception
* Run docker container
*/
private function runContainer(array $container, array $attributes)
private function runContainer()
{
$name = $container['name'];
$instance = $container['instance'];

putenv('INSTANCE_NAME='.$instance);

$this->info("Starting {$container['service']} $instance", false);

if (isset($attributes['command'])) {
$command = $attributes['command'];
} else {
if (isset($attributes['commands'])) {
$command = $attributes['commands'][$instance];
} else {
throw new Exception("Container {$container['service']} command or commands must be set");
}
}
putenv('CURRENT_INSTANCE='.$this->container['instance']);

if (isset($attributes['docker']['pre'])) {
foreach ($attributes['docker']['pre'] as $command) {
$this->docker->docker($command);
}
}

$command = '--name '.$name." ".$this->parseDotEnvVars($command);
$this->docker->run($command);
$this->info("Starting {$this->container['service']} #{$this->container['instance']}", false);

$network = isset($attributes['network']) ? $attributes['network'] : 'bridge';
$this->network[] = $this->getContainerNetwork($container, $network);
$this->preCommand();
$this->runCommand($this->getContainerCommand());
$this->postCommand();

if (isset($attributes['docker']['post'])) {
foreach ($attributes['docker']['post'] as $command) {
$this->docker->docker($command);
}
}
$this->setContainerNetwork();
}

/**
* @param string $container
* @param array $attributes
* Stop docker container
*/
private function stopContainer($container, array $attributes)
private function stop()
{
if ($this->option('service') != "") {
if (strtolower($this->option('service')) != strtolower($container)) {
collect($this->instances)->each(function ($container) {
$this->info("Stopping {$container['service']} #{$container['instance']}");

if (!$this->docker->isNamedContainerRunning($container['name'])) {
if ($this->confirm("{$container['service']} is not running, do you want start?")) {
$this->start();
}

return;
}
}

$containers = $this->getContainers($container, $attributes);

collect($containers)->each(function ($container) use ($container) {
$this->info("Stopping $container ".$container['instance']);
$this->docker->stopNamedContainer($container['name']);
$this->docker->removeNamedContainer($container['name']);
});
}


/**
* @param string $container
* @param array $attributes
* Restart docker containers
*/
private function restartContainer($container, array $attributes)
private function restart()
{
$this->info('Restarting '.$container);
$this->stopContainer($container, $attributes);
$this->startContainer($container, $attributes);
$this->stop();
$this->start();
}

/**
* Prepare environment
*
* @param string $container
* @param array $attributes
*
* @return array
*/
private function getContainerInstances($container, array $attributes)
private function prepare($container, array $attributes)
{
$name = strtolower('laravel-'.$container);
$instances = isset($attributes['instances']) ? (int)$attributes['instances'] : 1;
Expand All @@ -252,16 +244,19 @@ private function getContainerInstances($container, array $attributes)
putenv($envVar);
}

return $containers;
$this->instances = $containers;
$this->attributes = $attributes;
}

/**
* Parse environment variables
*
* @param $string
*
* @throws Exception
* @return string
*/
public function parseDotEnvVars($string)
public function parseEnvVars($string)
{
$found = preg_match_all('/((.*?)ENV\[([^|]+?)(\|(.+))?\](.*?))/', $string, $matches);

Expand All @@ -282,30 +277,103 @@ public function parseDotEnvVars($string)
}

/**
* @param array $container
* @param string $network
* Set container network information
*
* @return array
*/
private function getContainerNetwork($container, $network)
private function setContainerNetwork()
{
$host = $this->docker->getNamedContainerIp($container['name'], $network);
$port = $this->docker->getNamedContainerPorts($container['name']);
$network = isset($this->attributes['network']) ? $this->attributes['network'] : 'bridge';

return [
'service' => ucfirst($container['service']),
'host' => $host,
'port' => implode(", ", $port),
$host = $this->docker->getNamedContainerIp($this->container['name'], $network);
$port = $this->docker->getNamedContainerPorts($this->container['name']);

$this->network[] = [
'container' => ucfirst($this->container['service']).' #'.$this->container['instance'],
'host' => $host,
'port' => implode(", ", $port),
];
}

/**
* Render a console table displaying network information
* for each docker container running
*/
private function renderNetworkTable()
{
if (empty($this->network)) {
return;
}

$headers = ['Service', ' Host', 'Port'];
$headers = ['Container', 'Host', 'Port'];
$this->table($headers, $this->network);
}

/**
* Pull image from docker hub
*/
private function pullImage()
{
$tag = $this->attributes['repo'].':'.$this->attributes['tag'];
if (!$this->docker->imageExists($tag)) {
$this->docker->pull($tag);
}
}

/**
* Get normalized docker run command
*
* @return string
* @throws \Exception
*/
private function getContainerCommand()
{
$attributes = $this->attributes;

if (isset($attributes['command'])) {
$command = $attributes['command'];
} else {
if (isset($attributes['commands'])) {
$command = $attributes['commands'][$this->container['instance']];
} else {
throw new Exception("Container {$this->container['service']} command or commands must be set");
}
}

return '--name '.$this->container['name'].' '.$this->parseEnvVars($command);
}

/**
* Run pre execution commands
*/
private function preCommand()
{
if (isset($attributes['docker']['pre'])) {
foreach ($attributes['docker']['pre'] as $command) {
$this->docker->docker($this->parseEnvVars($command));
}
}
}

/**
* Run post execution commands
*/
private function postCommand()
{
if (isset($attributes['docker']['post'])) {
foreach ($attributes['docker']['post'] as $command) {
$this->docker->docker($this->parseEnvVars($command));
}
}
}

/**
* Perform docker run
*
* @param string $command
*/
private function runCommand($command)
{
$this->docker->run($command);
}
}

0 comments on commit a8d2d09

Please sign in to comment.