<?php
namespace Andweb\Yml;
use Nette;
class DefaultSettings
{
use Nette\SmartObject;
protected $arr;
public function getDefaultSettings()
{
$this->arr['version'] = '3.6';
$this->arr['ports']['mode'] = 'host';
$this->arr['labels']['name'] = 'aw-awesome-hosting';
$this->arr['labels']['value'] = 'yes';
$this->arr['deploy']['replicas'] = 1;
$this->arr['deploy']['restart_policy']['delay'] = "10s";
$this->arr['deploy']['restart_policy']['window'] = "30s";
$this->arr['deploy']['update_config'] = [
'parallelism' => 1,
'delay' => '30s',
'order' => 'stop-first',
];
$this->arr['deploy']['resources']['reservations'] = [
'cpus' => '0.25',
'memory' => '1G',
];
$this->arr['networks']['external'] = "true";
return $this->arr;
}
}
<?php
namespace App\ServiceModule\Presenters;
use Nette,
Andweb,
Symfony\Component\Yaml\Dumper,
Symfony\Component\Yaml\Yaml,
Andweb\Yml;
class YmlGeneratorPresenter extends Andweb\Application\UI\Presenter
{
/**
* Database connection
*
* @var Andweb\Database\Context
* @inject
*/
public $connection;
/* defaultni hodnoty */
protected $defaults;
/* pole ktere drzi hodnoty nase */
protected $arr;
public function __construct()
{
}
public function getDataFromRow($id = 1)
{
/* [2] Vyber dat z DB
---------------------------------------------------------------------------------------------------- */
// kontejner
$container = $this->connection->table('hosting_service_docker_container')->where('id', $id)->fetch();
$containerArr = $container->toArray();
// networks
$networks = $container->related('hosting_service_docker_container_network');
$networksArr = [];
foreach ($networks as $network)
{
$networksArr[] = $network->hosting_service_docker_network->name;
}
// ports
$ports = $container->related('hosting_service_docker_expose');
$portsArr = [];
$index = 0;
foreach ($ports as $port)
{
$portsArr[$index++] = [
'target' => $port->destination,
'published' => $port->source,
'protocol' => $port->proto,
//'mode' => $this->defaults['ports']['mode'], // doplneno v builderu
];
}
// volumes
$volumes = $container->related('hosting_service_docker_volume');
$volumesArr = [];
foreach ($volumes as $volume)
{
$volumesArr[] = implode(':', [ implode('/', [$volume->volume_dir, $volume->volume_file]), $volume->destination]);
}
// environments
$environments = $container->related('hosting_service_docker_env');
$environmentsArr = [];
foreach ($environments as $env)
{
$environmentsArr[$env->env_name] = $env->env_value;
}
return [
'container' => $container,
'containerArr' => $containerArr,
'networksArr' => $networksArr,
'volumesArr' => $volumesArr,
'portsArr' => $portsArr,
'environmentsArr' => $environmentsArr
];
}
public function actionYml()
{
$defaults = (new Yml\DefaultSettings)->getDefaultSettings();
$builder = new Yml\DockerComposeBuilder($defaults);
// hlavicka
$builder->createHeader();
// jednotlivy kontejnery
$builder->createSection($container1 = $this->getDataFromRow(1));
$builder->createSection($container2 = $this->getDataFromRow(2));
// paticka
$builder->createFooter($container1['networksArr']);
$builder->createFooter($container2['networksArr']);
// DUMP
$dumper = new Dumper();
$yaml = $dumper->dump($builder->getArr(), 7);
echo $yaml;
file_put_contents(INDEX_DIR . '/yml/demo.yml', $yaml);
$this->terminate();
}
public function actionArr()
{
$defaults = (new Yml\DefaultSettings)->getDefaultSettings();
$restorer = new Yml\RestoreResolver($defaults);
$restorer->resolveData(Yaml::parse(file_get_contents(INDEX_DIR . '/yml/demo-test.yml')));
\Tracy\Debugger::dump($restorer->getSanitizedData());
$this->terminate();
}
}
<?php
namespace Andweb\Yml;
use Nette;
class RestoreResolver
{
use Nette\SmartObject;
protected $defaults;
protected $arr;
public function __construct($defaults)
{
$this->defaults = $defaults;
}
public function resolveData($arr)
{
$this->arr = &$arr;
// version
$this->arr['version'] = $this->defaults['version'];
foreach ($arr['services'] as $sectionName => &$section)
{
$this->restoreSection($sectionName, $section);
}
// networks section
$this->reverseNetworks();
}
public function getSanitizedData()
{
return $this->arr;
}
protected function restoreSection($containerName, &$sectionArr)
{
$allowedKeys = [
'image',
'networks',
'ports',
'volumes',
'labels',
'deploy',
'environments'
];
foreach ($sectionArr as $itemName => &$vals)
{
if (!in_array($itemName, $allowedKeys))
{
unset($this->arr['services'][$containerName][$itemName]);
}
if (method_exists($this, 'serviceRestore'.$itemName))
{
$this->{'serviceRestore'.$itemName}($vals);
}
}
}
// subservices -- auto calls see above line: 60
public function serviceRestoreDeploy(&$deploy)
{
$allowedKeys = [
'deploy'
=> [
'replicas' => TRUE,
'restart_policy' => [
'condition' => TRUE,
'delay' => TRUE,
'window' => TRUE,
],
'update_config' => [
'parallelism' => TRUE,
'delay' => TRUE,
'order' => TRUE,
],
'resources' => [
'limits' => [
'memory' => TRUE,
'cpus' => TRUE,
],
'reservations' => [
'memory' => TRUE,
'cpus' => TRUE,
],
],
]
];
$this->arrayWalker($deploy, 0, $allowedKeys, ['deploy']);
}
public function arrayWalker(&$deploy, $level = 0, $allowedKeys, $key = [])
{
foreach ($deploy as $k => &$v)
{
if (is_array($v))
{
$merge = array_merge($key, [$k]);
$this->arrayWalker($v, $level + 1, $allowedKeys, $merge);
}
else
{
$keyPart = $key;
$keyPartK = array_merge($keyPart, [$k]);
$inWhiteList = & Nette\Utils\Arrays::getRef($allowedKeys, $keyPartK);
// DOPRDELE S TIM!, nema to tam co delat
if (!$inWhiteList)
{
unset($deploy[$k]);
}
$inDefaults = Nette\Utils\Arrays::get($this->defaults, $keyPartK, NULL);
if ($inDefaults)
{
$deploy[$k] = $inDefaults;
}
}
}
}
public function serviceRestoreLabels(&$label)
{
$label = []; // reset
$label[$this->defaults['labels']['name']] = $this->defaults['labels']['value'];
}
public function serviceRestorePorts(&$ports)
{
$allowedKeys = [
'target',
'published',
'protocol',
'mode',
];
$defaultSettingsKeys = [
'mode',
];
foreach ($ports as $index => &$arr)
{
foreach ($arr as $k => $v)
{
if (!in_array($k, $allowedKeys))
unset($arr[$k]);
if (in_array($k, $defaultSettingsKeys))
$arr[$k] = $this->defaults['ports'][$k];
}
}
}
protected function reverseNetworks()
{
foreach ($this->arr['networks'] as $networkSectionName => $network)
{
foreach ($network as $k => $v)
{
if ($k != 'external')
{
unset($this->arr['networks'][$networkSectionName][$k]);
}
else
{
$this->arr['networks'][$networkSectionName][$k] = $this->defaults['networks']['external'];
}
}
}
}
}
<?php
namespace Andweb\Yml;
use Nette;
class DockerComposeBuilder
{
use Nette\SmartObject;
protected $defaults;
protected $arr;
public function __construct($defaults)
{
$this->defaults = $defaults;
}
public function createHeader()
{
$this->arr = [
'version' => $this->defaults['version'],
'services' => []
];
}
public function createSection($data)
{
$containerArr = $data['containerArr'];
$containerArr = $data['containerArr'];
$networksArr = $data['networksArr'];
$volumesArr = $data['volumesArr'];
$portsArr = $data['portsArr'];
$environmentsArr = $data['environmentsArr'];
// Kontejner, jmeno - unikatni
$contName = $containerArr['name'];
//$this->arr['services'][$contName] = [];
$container = & $this->arr['services'][$contName];
// image
$container['image'] = $containerArr['image'];
// networks
$container['networks'] = $networksArr;
// ports
// doplneni defaultni hodnoty "mode"
foreach ($portsArr as & $arr)
$arr['mode'] = $this->defaults['ports']['mode'];
unset($arr); // https://coderwall.com/p/qx3fpa/php-foreach-pass-by-reference-do-it-right-or-better-not-at-all
$container['ports'] = $portsArr;
// ports
$container['volumes'] = $volumesArr;
// labels
$container['labels'] = [$this->defaults['labels']['name'] => $this->defaults['labels']['value']];
// deploy
$deploy = & $container['deploy'];
$deploy['replicas'] = $this->defaults['deploy']['replicas'];
$deploy['restart_policy'] = [
'condition' => $containerArr['restart_policy'],
'delay' => $this->defaults['deploy']['restart_policy']['delay'],
'window' => $this->defaults['deploy']['restart_policy']['window'],
];
$deploy['update_config'] = $this->defaults['deploy']['update_config'];
// deploy resources
$resources = & $deploy['resources'];
$resources['limits']['memory'] = $containerArr['quota_memory'];
$resources['limits']['cpus'] = $containerArr['quota_cpu'];
$resources['reservations']['cpus'] = $this->defaults['deploy']['resources']['reservations']['cpus'];
$resources['reservations']['memory'] = $this->defaults['deploy']['resources']['reservations']['memory'];
// environments
$container['environments'] = $environmentsArr;
}
public function createFooter($networks)
{
foreach ($networks as $network)
{
$this->arr['networks'][$network]['external'] = $this->defaults['networks']['external'];
}
}
public function getArr()
{
return $this->arr;
}
}