ソースを参照

Merged in FD3-712 (pull request #39)

FD3-712 instalación de composer. installer v2 desde images
Guillermo Espinoza 6 年 前
コミット
183e1d1aa3
6 ファイル変更1056 行追加39 行削除
  1. 3 10
      tools/Dockerfile
  2. 1 0
      tools/cmd.php
  3. 17 0
      tools/composer.sh
  4. 272 0
      tools/playbook_v2.yml
  5. 29 29
      tools/src/Release.php
  6. 734 0
      tools/src/ReleaseV2.php

+ 3 - 10
tools/Dockerfile

@@ -7,11 +7,10 @@ RUN wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
 RUN sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
 RUN apt-get update && apt-get install -yq python python-pip git vim tmux zip build-essential php7.1 iptables xz-utils php7.1-mbstring php7.1-gmp
 # mysql-client php7.1 php7.1-mysql php7.1-curl php7.1-xml php7.1-zip php7.1-bcmath php7.1-mbstring php7.1-dom php7.1-amqp php7.1-soap php7.1-snmp
+
 ## install composer
-RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
-RUN php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
-RUN php composer-setup.php --install-dir=/usr/local/bin --filename=composer
-RUN php -r "unlink('composer-setup.php');"
+ADD composer.sh /opt/composer.sh
+RUN chmod +x /opt/composer.sh ; ./opt/composer.sh
 
 ## install docker-composer
 #RUN curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
@@ -35,12 +34,6 @@ RUN ssh-keyscan -H -p 22  bitbucket.org >> ~/.ssh/known_hosts
 COPY keys /opt/keys
 RUN chmod 0600 /opt/keys/*
 
-## contains file to execute
-#RUN mkdir /opt/installation
-#RUN chmod -R 777 /opt/installation
-#ADD . /opt/installation
-#WORKDIR /opt/installation
-
 ARG DIR_INSTALL
 RUN mkdir -p $DIR_INSTALL
 RUN chmod -R 777 $DIR_INSTALL

+ 1 - 0
tools/cmd.php

@@ -8,6 +8,7 @@ use Symfony\Component\Console\Application;
 $app = new Application();
 
 $app->add(new FD3\Release());
+$app->add(new FD3\ReleaseV2());
 $app->add(new FD3\GetSource());
 $app->add(new FD3\MergeHostsFile());
 $app->add(new FD3\DockerInventory());

+ 17 - 0
tools/composer.sh

@@ -0,0 +1,17 @@
+#!/bin/sh
+
+EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)"
+php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+ACTUAL_SIGNATURE="$(php -r "echo hash_file('SHA384', 'composer-setup.php');")"
+
+if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
+then
+    >&2 echo 'ERROR: Invalid installer signature'
+    rm composer-setup.php
+    exit 1
+fi
+
+php composer-setup.php --quiet --install-dir=/usr/local/bin --filename=composer
+RESULT=$?
+rm composer-setup.php
+exit $RESULT

+ 272 - 0
tools/playbook_v2.yml

@@ -0,0 +1,272 @@
+---
+
+- name: Launch docker for mysql database. Tag=start_mysql
+  hosts: 127.0.0.1
+  connection: local
+  tags: start_mysql
+  tasks:
+
+    - name: Docker mysql up
+      command: "docker-compose up -d --force-recreate mysql"
+
+- name: Configure mysql database. Tag=configure_mysql
+  hosts: mysql
+  connection: docker
+  gather_facts: no
+  tags: configure_mysql
+  tasks:
+    - name: Wait for mysql be ready
+      wait_for:
+        host: 127.0.0.1
+        port: 3306
+        state: started
+        delay: 5
+        connect_timeout: 15
+        timeout: 360
+
+    - name: Create database fd_session
+      mysql_db:
+        name: fd_session
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database freeradius
+      mysql_db:
+        name: freeradius
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database grafana
+      mysql_db:
+        name: grafana
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database statsd_db
+      mysql_db:
+        name: statsd_db
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database base
+      mysql_db:
+        name: fd3_base
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database ftth
+      mysql_db:
+        name: fd3_ftth
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database mapas
+      mysql_db:
+        name: fd3_mapas
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database stats
+      mysql_db:
+        name: fd3_stats
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database cablemodem
+      mysql_db:
+        name: fd3_cablemodem
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database Radius
+      mysql_db:
+        name: fd3_radius
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - name: Create database dhcp
+      mysql_db:
+        name: fd3_dhcp
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: present
+
+    - copy:
+        src: "{{ playbook_dir }}/freeradius_schema.sql"
+        dest: /tmp/freeradius_schema.sql
+
+    - name: Create freeradius MySQL schema
+      mysql_db:
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: import
+        name: freeradius
+        target: "/tmp/freeradius_schema.sql"
+
+    - name: Create user iksop
+      mysql_user:
+        name: 'iksop'
+        password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        priv: '*.*:ALL'
+        state: present
+
+    - copy:
+        src: "{{ playbook_dir }}/mysql_scripts.sql"
+        dest: /tmp/mysql_scripts.sql
+
+    - name: Replace password mysql_scripts.sql
+      shell: "sed -i -- 's/#password#/{{ lookup('env', 'MYSQL_PASSWORD') }}/g' /tmp/mysql_scripts.sql"
+
+    - name: Run SQL commands against DB to create table
+      mysql_db:
+        login_password: "{{ lookup('env', 'MYSQL_PASSWORD') }}"
+        state: import
+        name: fd_session
+        target: "/tmp/mysql_scripts.sql"
+
+- name: Launch docker for amqp. Tag=start_amqp
+  hosts: 127.0.0.1
+  connection: local
+  tags: start_base
+  tasks:
+    - name: Docker base up
+      command: "docker-compose up -d amqp"
+
+    - name: "Wait for amqp. Timeout: 1 minutes"
+      pause:
+        minutes: 1
+
+- name: Launch docker for module base. Tag=start_base
+  hosts: 127.0.0.1
+  connection: local
+  tags: start_base
+  tasks:
+    - name: Docker base up
+      command: "docker-compose up -d --force-recreate base"
+
+- name: Configure module base. Tag=configure_base
+  hosts: base
+  connection: docker
+  tags: configure_base
+  vars:
+    uris: ""
+  tasks:
+    - name: "Wait for autoload_classmap.php. Timeout: 10 minutes"
+      wait_for:
+          path: "/opt/base/vendor/composer/autoload_classmap.php"
+          state: present
+          sleep: 30
+          timeout: 600
+
+    - name: Load redirections
+      set_fact:
+        uris: "{{ uris }} --redirect_uri=https://{{ item }}.{{ lookup('env', 'CLIENT') }}.flowdat.net/login_check"
+      with_items: "{{ lookup('env', 'MODULES_INSTALL').split(',') }}"
+
+    - name: Load redirections app_dev
+      set_fact:
+        uris: "{{ uris }} --redirect_uri=https://{{ item }}.{{ lookup('env', 'CLIENT') }}.flowdat.net/app_dev.php/login_check"
+      with_items: "{{ lookup('env', 'MODULES_INSTALL').split(',') }}"
+
+    - name: Create oauth client
+      shell: "bin/console oauth:client:createRedirects {{ uris }} > oauth.data.log"
+      args:
+        executable: /bin/bash
+
+    - name: Update variable usersetting
+      set_fact:
+        usersetting: "{{ lookup('file', '{{ playbook_dir }}/user_system.json')|from_json }}"
+
+    - name: Create user iksop
+      shell: "bin/console user:create {{ item.user }} {{ item.email }} {{ item.password }} {{ item.tenancy }} {{ item.extra }}"
+      args:
+        executable: /bin/bash
+      with_items: "{{ usersetting.users }}"
+
+    - name: Promote users to ADMIN
+      shell: " bin/console fos:user:promote admin ROLE_ADMIN"
+      args:
+        executable: /bin/bash
+
+    - name: Promote users to IKSOP
+      shell: " bin/console fos:user:promote iksop ROLE_SUPER_ADMIN"
+      args:
+        executable: /bin/bash
+
+    - name: Copy file oauth.data.log to host
+      fetch:
+        src: /opt/base/oauth.data.log
+        dest: /tmp/
+        flat: yes
+
+- name: Configure oauth data for other container. Tag=configure_oauth
+  hosts: 127.0.0.1
+  connection: local
+  tags: configure_oauth
+  tasks:
+    - name: "Add outh client id"
+      shell:  "cp /tmp/oauth.data.log {{ item }}.oauth.env"
+      args:
+        executable: /bin/bash
+      with_items: "{{ lookup('env', 'MODULES_INSTALL').split(',') }}"
+
+- name: "Launch docker's. Tag=launch_dockers"
+  hosts: 127.0.0.1
+  connection: local
+  tags: launch_dockers
+  tasks:
+    - name: "Dockers up"
+      command: "docker-compose up -d --force-recreate {{ item }}"
+      with_items: "{{ lookup('env', 'MODULES_INSTALL').split(',') }}"
+
+- name: "Run modules. Timeout: 10 minutes. Tag=run_modules"
+  hosts: "{{ lookup('env', 'MODULES_INSTALL') }}"
+  connection: docker
+  tags: run_modules
+  tasks:
+    - name: "Docker's schema update"
+      wait_for:
+        path: "./vendor/composer/autoload_classmap.php"
+        state: present
+        sleep: 30
+        timeout: 600
+
+- name: "Run doctrine:schema:update for modules. Tag=dsu_modules"
+  hosts: "{{ lookup('env', 'MODULES_INSTALL') }}"
+  connection: docker
+  tags: dsu_modules
+  tasks:
+    - name: "Doctrine schema update"
+      shell: "bin/console doctrine:schema:update --force"
+
+  # Generate self-signed cert files for Nginx (intended for development, please replace with proper ones)
+- name: "Generate self-signed cert files for Nginx"
+  hosts: 127.0.0.1
+  connection: local
+  tags: self_cert
+  tasks:
+    - name: "Make sure certs dir exists"
+      shell: "mkdir -p /opt/flowdat/certs"
+    - name: "Generate self-signed certs for Nginx"
+      shell: "openssl req -x509 -nodes -batch -days 365 -newkey rsa:2048 -keyout /opt/flowdat/certs/privkey.pem -out /opt/flowdat/certs/fullchain.pem -subj '/C=AR/ST=Santa Fe/L=Rosario/O=Interlink/OU=R&D/CN=*.{{ lookup('env','CLIENT') }}.{{ lookup('env','DOMAIN') }}/emailAddress=idev@interlink.com.ar'"
+
+- name: "Copy certs dir to extra/nginx/certs"
+  hosts: 127.0.0.1
+  connection: local
+  tags: copy_cert
+  tasks:
+    - name: "Copy certs directory"
+      shell: "cp -nr /opt/flowdat/certs/* /opt/flowdat/extra/nginx/certs"
+
+- name: "Run up all. Tag=up_all"
+  hosts: 127.0.0.1
+  connection: local
+  tags: up_all 
+  tasks:
+    - name: Docker up all modules
+      command: "docker-compose up -d "
+
+    - name: Docker stop nginx
+      command: "docker-compose stop nginx "
+
+    - name: Docker up nginx
+      command: "docker-compose up -d nginx"

+ 29 - 29
tools/src/Release.php

@@ -20,71 +20,71 @@ class Release extends Command
     /**
      * @var string Nombre del archivo de log.
      */
-    private $_running_log;
+    protected $_running_log;
 
     /**
      * @var string Contiene la politica de restart de los dockers.
      */
-    private $_docker_restart_default;
+    protected $_docker_restart_default;
 
     /**
      * @var array Contiene las variables que se utilizar en la ejecucion del ansible.
      */
-    private $_ansible_vars;
+    protected $_ansible_vars;
 
     /**
      * @var string Contiene el password del usuario root.
      */
-    private $_mysql_root_pass;
+    protected $_mysql_root_pass;
 
     /**
      * @var string Contiene el usuario de base de datos.
      */
-    private $_mysql_user;
+    protected $_mysql_user;
 
     /**
      * @var string Contiene la contrasena del  usuario de base de datos.
      */
-    private $_mysql_pass;
+    protected $_mysql_pass;
 
     /**
      * @var DevOps\FileSystem Me permite crear archivos.
      */
-    private $_dObj;
+    protected $_dObj;
 
     /**
      * @var string Contiene el dominio.
      */
-    private $_domain;
+    protected $_domain;
 
     /**
      * @var string Contiene el nombre del cliente.
      */
-    private $_client;
+    protected $_client;
 
     /**
      * @var array Contiene todos los modulos para la instalacion.
      */
-    private $_modules_all;
+    protected $_modules_all;
 
     /**
      * @var array Contiene la configuracion de los modulos.
      */
-    private $_modules;
+    protected $_modules;
     /**
      * @var array Contiene los usuarios que van a poder acceder al sistema.
      */
-    private $_user_system;
+    protected $_user_system;
 
     /**
      * @var string $directory Directorio de instalacion
      */
-    private $directory;
+    protected $directory;
     
     /**
      * @var boolean $_use_nginx_links Para indicar si se crean los links nginx entre los modulos
      */
-    private $_use_nginx_links;
+    protected $_use_nginx_links;
 
     /**
      * Constructor.
@@ -1188,7 +1188,7 @@ class Release extends Command
      * Crea un array con la configuracion de los modulos.
      * @param InputInterface $input Contiene el input.
      */
-    private function addConfigOptions(InputInterface $input)
+    protected function addConfigOptions(InputInterface $input)
     {
         foreach ($this->_modules as $key => $values) {
             if ($input->hasOption($key . "-repo") &&
@@ -1205,7 +1205,7 @@ class Release extends Command
     /**
      * Crea un array con las direcciones de a clonar.
      */
-    private function createGitClone()
+    protected function createGitClone()
     {
         $clone = array();
         $modules = array_keys($this->_modules);
@@ -1226,7 +1226,7 @@ class Release extends Command
      * @param InputInterface $input Contiene el input
      * @param OutputInterface $output Contiene el output
      */
-    private function createFileRunning(InputInterface $input, OutputInterface $output)
+    protected function createFileRunning(InputInterface $input, OutputInterface $output)
     {
         $file = array();
         $file ["Running"] = array("date" => gmdate('Y-m-d h:i:s'));
@@ -1269,7 +1269,7 @@ class Release extends Command
     /**
      * Crea el archivo modulo.oauth.env
      */
-    private function writeOAUTH()
+    protected function writeOAUTH()
     {
         $oautModules = "";
         foreach ($this->_modules as $nameApp => $app) {
@@ -1284,7 +1284,7 @@ class Release extends Command
     /**
      * Crea el archivo host.env
      */
-    private function writeHostEnv()
+    protected function writeHostEnv()
     {
         $hostEnvConfig = $this->getHostEnv();
         $env_content = "";
@@ -1298,7 +1298,7 @@ class Release extends Command
      * Crea el archivo hostsDile
      * @param string $config_ip Contiene la ip.
      */
-    private function writeHostsFile($config_ip)
+    protected function writeHostsFile($config_ip)
     {
         $hostConfig = $this->getHostConfig($config_ip);
         $hostfile_content = "";
@@ -1314,7 +1314,7 @@ class Release extends Command
      * @param string $module Contiene el nombre del modulo.
      * @param array $extras Contiene un array con las variables extras.
      */
-    private function writeVariablesEnviroment($name, $module = null, $extras = array())
+    protected function writeVariablesEnviroment($name, $module = null, $extras = array())
     {
         $this->_dObj->file($name)->content(
             $this->getEnviromentVarialbes($name, $module, $extras));
@@ -1325,7 +1325,7 @@ class Release extends Command
      * @param string $module Contiene el nombre del modulo.
      * @param FileFormat2 $composer Contiene el objeto FileFormat2.
      */
-    private function addBuild($module, FileFormat2 $composer)
+    protected function addBuild($module, FileFormat2 $composer)
     {
         if (isset($this->_modules[$module]['build']) &&
             filter_var($this->_modules[$module]['build'], FILTER_VALIDATE_BOOLEAN)) {
@@ -1343,7 +1343,7 @@ class Release extends Command
      * otro directorio.
      * @param InputInterface $input contiene el input
      */
-    private function setParametersFormFile(InputInterface $input)
+    protected function setParametersFormFile(InputInterface $input)
     {
         $parameters = parse_ini_file($input->getArgument('dir') . "/" . $this->_running_log, true);
         foreach ($parameters["Options"] as $key => $value) {
@@ -1355,7 +1355,7 @@ class Release extends Command
      * @param string $module Contiene el nombre del modulo.
      * @return string Retorna el dominio para el modulo.
      */
-    private function getDomain($module)
+    protected function getDomain($module)
     {
         return $module . "." . $this->_client . "." . $this->_domain;
     }
@@ -1363,7 +1363,7 @@ class Release extends Command
     /**
      * @param array $modules Contiene los modulos a implementar
      */
-    private function AddModules($modules)
+    protected function AddModules($modules)
     {
         foreach ($modules as $value) {
             if (array_key_exists($value, $this->_modules_all)) {
@@ -1375,7 +1375,7 @@ class Release extends Command
     /**
      * Crea el archivo con las variables para ejecutar el ansible.
      */
-    private function writeEnvVariables()
+    protected function writeEnvVariables()
     {
         $tmp = "";
         foreach ($this->_ansible_vars as $key => $value) {
@@ -1388,7 +1388,7 @@ class Release extends Command
     /**
      * Crea el archivo con los usuarios del sistema para que lea el ansible.
      */
-    private function writeUserSystem()
+    protected function writeUserSystem()
     {
         $this->_dObj->file("user_system.json")
             ->content(json_encode($this->_user_system));
@@ -1397,7 +1397,7 @@ class Release extends Command
     /**
      * Crea el archivo con las variables para ejecutar el ansible.
      */
-    private function writeInventory(FileFormat2 $composer)
+    protected function writeInventory(FileFormat2 $composer)
     {
         $tmp = "";
         $all = "[all]\n";
@@ -1416,7 +1416,7 @@ class Release extends Command
      * @param string $module Contiene el nombre del modulo.
      * @param FileFormat2 $composer Contiene el objeto FileFormat2.
      */
-    private function addNginxLinks($module, FileFormat2 $composer)
+    protected function addNginxLinks($module, FileFormat2 $composer)
     {
         if ($this->_add_nginx_links) {
             $composer->service($module)

+ 734 - 0
tools/src/ReleaseV2.php

@@ -0,0 +1,734 @@
+<?php
+
+namespace FD3;
+
+use Docker\Composer\ServiceNotFoundException;
+use League\Flysystem\File;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Docker\Composer\FileFormat2;
+use Symfony\Component\Console\Exception\LogicException;
+use Symfony\Component\Console\Question\ConfirmationQuestion;
+use Symfony\Component\Yaml\Yaml;
+
+class ReleaseV2 extends Release
+{
+    
+    protected function configure()
+    {
+        $this
+            ->setName('make:install:v2')
+            ->setDescription('Create a new install files.')
+            ->setHelp('This command allows you to create a new installation files...')
+            ->addArgument('dir', InputArgument::REQUIRED, 'The directory where to create the installation.')
+            ->addOption('client', null, InputOption::VALUE_REQUIRED, 'Client name, if is not provided uses, the dirname of the installation', false)
+            ->addOption('domain', null, InputOption::VALUE_REQUIRED, 'Domain where the flowdat will be installed', 'flowdat.net')
+            ->addOption('host-ip', null, InputOption::VALUE_REQUIRED, 'Ip of the runnning host to be added to the /etc/hosts file, eventually', '127.0.1.1')
+            ->addOption('modules', null, InputOption::VALUE_REQUIRED, 'List of modules to install separated by coma.', 'all')
+            ->addOption('docker-tag', null, InputOption::VALUE_REQUIRED, 'Docker tag to be used. Ej. v0.1.1', 'latest')
+            ->addOption('add-nginx-links', null, InputOption::VALUE_NONE, 'Add NGINX links between dockers', null)
+            ;
+    }
+    
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        try {
+            // Módulos a instalar
+            $modules = explode(',', $input->getOption('modules'));
+            if ($modules[0] == 'all') {
+                $modules = [];
+                foreach ($this->_modules_all as $name => $value) {
+                    if (isset($value['MODULE_INSTALL']) && $value['MODULE_INSTALL']) {
+                        $modules[] = $name;
+                    }
+                }
+            }
+                        
+            $this->AddModules($modules);
+            
+            // Agrego el repositorio de extra únicamente
+            $this->_modules['extra']['repo'] = 'git@bitbucket.org:ikflowdat/extra.git';
+            $this->_modules['extra']['ref'] = 'master';
+            
+            $this->directory = $input->getArgument('dir');
+            if (!is_dir($this->directory)) {
+                mkdir($this->directory, 0777, true);
+            }
+            if (file_exists($this->directory . '/' . $this->_running_log)) {
+                $helper = $this->getHelper('question');
+                $question = new ConfirmationQuestion('The ' . realpath($this->directory) . '/' . $this->_running_log . ' file exist. Read file or take parameters? (Y/n)', true);
+                if ($helper->ask($input, $output, $question)) {
+                    $this->setParametersFormFile($input);
+                }
+            }
+            $this->_domain = $input->getOption('domain');
+            $this->_client = $input->getOption('client') ?: basename(realpath($this->directory));
+            $docker_tag = $input->getOption('docker-tag');
+            
+            $this->internal_user_id = 2;
+            $this->_ansible_vars = [
+                'DOMAIN' => $this->_domain,
+                'CLIENT' => $this->_client,
+                'CMD_USERNAME' => $this->_user_system['users'][$this->internal_user_id]['user'],
+                'CMD_PASSWORD' => $this->_user_system['users'][$this->internal_user_id]['password'],
+                'ENV_LIST' => 'prod,dev,test',
+                'API_CIDR' => '172.20.0.0/24',
+                'MYSQL_ROOT_PASSWORD' => $this->_mysql_root_pass,
+            ];
+                        
+            $this->_add_nginx_links = (boolean)$input->getOption('add-nginx-links');
+
+            $this->_dObj = new DevOps\FileSystem(realpath($this->directory));
+            $this->_dObj->dirExists()->realpath();
+            
+            // agrego las opciones del input a la configuracion _modues
+            $this->addConfigOptions($input);
+            // creo el archivo de log de como se ejecuto
+            $this->createFileRunning($input, $output);
+            // cargo las fuentes a clonar
+            $this->createGitClone();
+            // creo el archivo docker-compose.yml
+            $this->getDockerCompose($docker_tag, "host.env", "docker.infra.flowdat.com/");
+            // escribo el archivo de host
+            $this->writeHostsFile($input->getOption("host-ip"));
+            // escribo el archivo con las variables de entorno
+            $this->writeHostEnv();
+            // escribo los archivo oauth
+            $this->writeOAUTH();
+            // escribo un archivo con variables para ansible
+            $this->writeEnvVariables();
+            // escribo un archivo con los usuarios del sistema
+            $this->writeUserSystem();
+
+            $this->_dObj->file('install.yml')->content(
+                yaml::dump(array(
+                        "install_dir" => realpath($this->directory),
+                        'docker_apps' => "base," . implode(",", $this->_ansible_vars),
+                        'domain' => $this->_domain,
+                    )
+                )
+            );
+
+            $this->_dObj->file('ansible.cfg')->content(
+                "[defaults]\n" .
+                "inventory=inventory.ini\n"
+            );
+            
+            $path = $this->_dObj->dirExists()->realpath()->getPath();
+
+            // copio el playbook
+            copy(getcwd() . "/playbook_v2.yml", $path . "/playbook.yml");
+            // copio el script de base de datos inicial
+            copy(getcwd() . "/mysql_scripts.sql", $path . "/mysql_scripts.sql");
+            // copio el archivo que contiene los usuarios del sistema
+            copy(getcwd() . "/user_system.json", $path . "/user_system.json");
+            // copio script mysql schema freeradius
+            copy(getcwd() . "/mysql/freeradius/schema.sql", $path . "/freeradius_schema.sql");
+            // copio el docker-compose.service
+            copy(getcwd() . "/docker-compose.service", $path . "/docker-compose.service");
+            // copio el archivo con variables de entorno de grafana
+            copy(getcwd() . "/grafana.env", $path . "/grafana.env");
+        } catch (\Throwable $error) {
+            throw $error;
+        } finally {
+            $this->_dObj = null;
+            $this->_modules = null;
+        }
+    }
+        
+    /**
+     * @param string $version
+     * @param string $host_env_file
+     * @param string $registry
+     */
+    function getDockerCompose($version = "latest", $host_env_file = "host.env", $registry = "docker.infra.flowdat.com/")
+    {
+        $composer = new FileFormat2("../");
+        
+        $volumes = [
+            'pma', 'base', 'cablemodem', 'cablemodem_upload', 'dhcp', 'ftth', 
+            'mapas', 'mapas_upload', 'radius', 'stats', 'radius', 'stats', 'kea', 
+            'geoserver', 'grafana', 'mysql', 'mongodb',
+        ];
+        foreach ($volumes as $volume) {
+            $composer->getVolumes()->addVolumen("{$volume}_volumen", 'local');
+        }
+        
+        $base_vars = array(
+            "version" => $version,
+            "host_env_file" => $host_env_file,
+            "registry" => $registry
+        );
+
+        $this->addNginx($composer, $base_vars);
+
+        /**************************************************************************************/
+        /* Apps / Web UI / Grafana / PMA */
+        /**************************************************************************************/
+        foreach ($this->_modules_all as $module => $env) {
+            $method = 'add' . ucfirst($module);
+            if (array_key_exists($module, $this->_modules) && method_exists($this, $method)) {
+                $this->$method($composer, $base_vars);
+            }
+        }
+
+        /**************************************************************************************/
+        /* Servicios */
+        /**************************************************************************************/
+        $this->addMySql($composer, $base_vars);
+        
+        $this->addPma($composer, $base_vars);
+        
+        $composer
+            ->addService("amqp")
+            ->build("./extra/amqp/")
+            ->image("rabbitmq:3-management")
+            ->addPorts(15674, 15674)
+            ->addPorts(15672, 15672)
+            ->restart($this->_docker_restart_default);
+            
+        $this->addMongDb($composer, $base_vars);
+        
+        $this->addRedis($composer, $base_vars);
+        
+        $this->addGenieACS($composer, $base_vars);
+        
+        $this->addFreeradius($composer, $base_vars);
+
+        /**************************************************************************************/
+        /* Workers */
+        /**************************************************************************************/
+        $this->addSupervisord($composer, $base_vars);
+        $this->addCommandWorkers($composer, $base_vars);
+
+        $this->addTftp($composer, $base_vars);
+
+        // Geoserver
+        $this->addGeoserver($composer, $base_vars);
+
+        // Kea
+        $this->addKea($composer, $base_vars);
+
+        // Swagger
+        $this->addSwagger($composer, $base_vars);
+        $this->addApi($composer, $base_vars);
+
+        $this->_dObj->file("docker-compose.yml")->content($composer->render());
+
+        // escribo un archivo inventory.ini por defecto para no tener que lanzar los docker
+        $this->writeInventory($composer);
+    }
+    
+    public function aux1(FileFormat2 $composer, $module, $config = array())
+    {
+        $version = "latest";
+        $registry = "";
+        $host_env_file = "";
+        extract($config);
+        
+        return $composer
+            ->addService($module)
+            ->image("{$registry}fd3/{$module}:{$version}")
+            ->restart($this->_docker_restart_default)
+            ->addEnv_file($host_env_file);
+    }
+    
+    public function aux2(FileFormat2 $composer, $module, $config = array())
+    {
+        $version = "latest";
+        $host_env_file = "";
+        extract($config);
+        
+        $service = $this->aux1($composer, $module, $config);
+        
+        $service
+            ->addLinks("mysql:mysql")
+            ->addEnv_file("running.env")
+            ->addEnv_file("{$module}.{$host_env_file}")
+            ->addVolumes("{$module}_volumen", "/opt/{$module}")
+            ;
+            
+        $this->addNginxLinks($module, $composer);
+
+        $this->writeVariablesEnviroment("{$module}.{$host_env_file}", $module);
+        
+        return $service;
+    }
+    
+    public function aux3(FileFormat2 $composer, $module, $config = array())
+    {
+        $service = $this->aux2($composer, $module, $config);
+        
+        return $service
+            ->addLinks("base")
+            ->addEnv_file("{$module}.oauth.env")
+            ;
+    }
+        
+    function addNginx(FileFormat2 $composer, $config = array())
+    {
+        $composer = $this->aux1($composer, 'nginx', $config);
+        
+        $composer
+            ->addPorts(80, 80)
+            ->addPorts(443, 443)
+            ->addVolumes("base_volumen", "/opt/base")
+            ->addVolumes("ftth_volumen", "/opt/ftth")
+            ->addVolumes("mapas_volumen", "/opt/mapas")
+            ->addVolumes("radius_volumen", "/opt/radius")
+            ->addVolumes("stats_volumen", "/opt/stats")
+            ->addVolumes("cablemodem_volumen", "/opt/cablemodem")
+            ->addVolumes("dhcp_volumen", "/opt/dhcp")
+            ->addVolumes("grafana_volumen", "/opt/grafana")
+            ->addVolumes("pma_volumen", "/opt/pma")
+            ->addVolumes("/var/run/docker.sock", "/tmp/docker.sock:ro")
+            ->addVolumes('./extra/api/', '/opt/api')
+            ->addVolumes("./extra/nginx/certs", "/etc/nginx/certs:ro")
+            ->addVolumes("./extra/nginx/conf.d", "/etc/nginx/conf.d")
+            ->addVolumes("./extra/nginx/share", "/usr/share/nginx/html");
+    }
+
+    function addBase(FileFormat2 $composer, $config = array())
+    {
+        $this->aux2($composer, 'base', $config);
+    }
+
+    function addFtth(FileFormat2 $composer, $config = array())
+    {
+        $composer = $this->aux3($composer, 'ftth', $config);
+        
+        $composer
+            ->addVolumes("./extra/netmiko", "/opt/netmiko")
+            ->addVolumes("./extra/backups-config", "/opt/ftth/web/backups-config");
+    }
+
+    function addStats(FileFormat2 $composer, $config = array())
+    {
+        $composer = $this->aux3($composer, 'stats', $config);
+        
+        $composer->addLinks("jsonep_mysql:jsonep_mysql");
+    }
+
+    function addMapas(FileFormat2 $composer, $config = array())
+    {
+        $module = 'mapas';
+        
+        $composer = $this->aux3($composer, $module, $config);
+        
+        $composer
+            ->addVolumes("{$module}_upload_volumen", "/opt/{$module}/web/uploads");
+    }
+
+    function addCablemodem(FileFormat2 $composer, $config = array())
+    {
+        $module = 'cablemodem';
+        
+        $composer = $this->aux3($composer, $module, $config);
+
+        $composer
+            ->addVolumes("{$module}_upload_volumen", "/opt/{$module}/web/uploads");
+    }
+
+    /**
+     * atftp, tod
+     *
+     * @param FileFormat2 $composer
+     * @param array $config
+     */
+    function addTftp(FileFormat2 $composer, $config = array())
+    {
+        $composer = $this->aux1($composer, 'tftp', $config);
+        
+        $composer->addPorts(69, '69/udp');
+    }
+
+    function addRadius(FileFormat2 $composer, $config = array())
+    {
+        $composer = $this->aux3($composer, 'radius', $config);
+    }
+
+    function addDHCP(FileFormat2 $composer, $config = array())
+    {
+        $composer = $this->aux3($composer, 'dhcp', $config);
+        
+        $composer
+        // ->addVolumes("./kea/conf", "/opt/dhcp/web/kea")
+            ->addVolumes("kea_volumen", "/opt/dhcp/web/kea");
+    }
+    
+    function addApi(FileFormat2 $composer, $config = array())
+    {
+        $module = "api";
+        $host_env_file = "";
+        extract($config);
+        
+        $service = $this->aux1($composer, $module, $config);
+        
+        $service
+            ->addEnv_file("running.env")
+            ->addEnv_file("{$module}.{$host_env_file}")
+            ->addVolumes("./extra/{$module}/", "/opt/{$module}")
+            ;
+            
+        $this->addNginxLinks($module, $composer);
+
+        $this->writeVariablesEnviroment("{$module}.{$host_env_file}", $module);
+    }
+
+    function addMongDb(FileFormat2 $composer, $config = array())
+    {
+        $mongdb_version = "3.4";
+        extract($config);
+
+        $composer
+            ->addService("mongodb")
+            ->image("mongo:" . $mongdb_version)
+            ->addVolumes("mongodb_volumen", "/data/db")
+            // ->addVolumes("./mongodb", "/data/db")
+            ->mem_limit('10g');
+    }
+
+    /**
+     * @param FileFormat2 $composer
+     * @param array $config
+     */
+    function addSupervisord(FileFormat2 $composer, $config = array())
+    {
+        $service = $this->aux1($composer, 'supervisord', $config);
+        
+        $service
+            ->privileged(true)
+            ->addLinks("geoserver")
+            ->addLinks("nginx", $this->getDomain("geoserver"))
+            ->addVolumes("./extra/supervisord/", "/etc/supervisord/")
+            ->addVolumes("./extra/supervisord/var/", "/var/log/supervisor/")
+            ->addVolumes("./extra/supervisord/sshd_config", "/etc/ssh/sshd_config")
+            ->addVolumes("./extra/supervisord/bin/fiberhome", "/usr/bin/fiberhome")
+            ->addVolumes("./extra/supervisord/bin/fiberlink", "/usr/bin/fiberlink")
+            ->addVolumes("./extra/supervisord/bin/huawei", "/usr/bin/huawei")
+            ->addVolumes("./extra/supervisord/bin/zte", "/usr/bin/zte")
+            ->addVolumes("stats_volumen", "/opt/stats")
+            ->addVolumes("ftth_volumen", "/opt/ftth")
+            ->addEnv_file("running.env")
+            ->addEnv_file("stats.host.env")
+            ->addEnv_file("stats.oauth.env");
+    }
+
+    function addMySql(FileFormat2 $composer, $config = array())
+    {
+        $module = "mysql";
+        $host_env_file = "";
+        extract($config);
+        
+        $service = $this->aux1($composer, $module, $config);
+        
+        $service
+        // ->addVolumes("./mysql/", "/var/lib/mysql/")
+            ->addVolumes("mysql_volumen", "/var/lib/mysql/")
+            ->addVolumes("./extra/mysql/fd3.conf", "/etc/mysql/conf.d/fd3.conf");
+            
+        $this->writeVariablesEnviroment("{$module}.{$host_env_file}", $module,
+            array(
+                "MYSQL_ROOT_PASSWORD" => $this->_mysql_root_pass,
+                "MYSQL_USER" => $this->_mysql_user,
+                "MYSQL_PASSWORD" => $this->_mysql_pass,
+                "MYSQL_MAX_CONNECTIONS" => $this->_mysql_max_connections,
+            ));
+    }
+
+    function addRedis(FileFormat2 $composer, $config = array(), $flavor = "dev")
+    {
+        $composer
+            ->addService("redis")
+            ->image("redis:latest")
+            ->command("redis-server --appendonly yes")
+            ->restart($this->_docker_restart_default);
+    }
+
+    function addGenieACS(FileFormat2 $composer, $config = array(), $flavor = "dev")
+    {
+        extract($config);
+        
+        $composer
+            ->addService("genieacs-cwmp")
+            ->image($registry . "fd3/genieacs-cwmp:" . $version)
+            ->addLinks("mongodb")
+            ->addLinks("redis")
+            ->addPorts("7547", "7547")
+            ->restart($this->_docker_restart_default);
+
+        $composer
+            ->addService("genieacs-nbi")
+            ->image($registry . "fd3/genieacs-nbi:" . $version)
+            ->addLinks("mongodb")
+            ->addLinks("redis")
+            ->addPorts("7557", "7557")
+            ->restart($this->_docker_restart_default);
+
+        $composer
+            ->addService("genieacs-fs")
+            ->image($registry . "fd3/genieacs-fs:" . $version)
+            ->addLinks("mongodb")
+            ->addLinks("redis")
+            ->addPorts("7567", "7567")
+            ->restart($this->_docker_restart_default);
+
+        $composer
+            ->addService("genieacs-gui")
+            ->image($registry . "fd3/genieacs-gui:" . $version)
+            ->addLinks("genieacs-nbi")
+            ->addPorts("3001", "3000")
+            ->restart($this->_docker_restart_default);
+    }
+
+    function addFreeradius(FileFormat2 $composer, $config = array(), $flavor = "dev")
+    {
+        $module = "freeradius";
+        $host_env_file = "";
+        extract($config);
+        
+        $service = $this->aux1($composer, $module, $config);
+        
+        $service
+            ->addLinks("mysql")
+            ->addPorts("1812:1812/udp")
+            ->addPorts("1813:1813/udp")
+            ->addPorts("3799:3799/udp")
+            ->addEnv_file("mysql.{$host_env_file}")
+            ->addVolumes("./extra/freeradius/wsdl/code/", "/var/www/html/")
+            ->addVolumes("./extra/freeradius/etc/cron.d", "/etc/cron.d")
+            ->addVolumes("./extra/freeradius/etc/freeradius", "/etc/freeradius")
+            ->addVolumes("./extra/freeradius/etc/supervisor/conf.d", "/etc/supervisor/conf.d");
+            
+        $this->writeVariablesEnviroment("{$module}.{$host_env_file}", $module,
+            array(
+                "MYSQL_HOST" => "mysql",
+            ));
+    }
+
+    function addPma(FileFormat2 $composer, $config = array())
+    {
+        $module = "pma";
+        $host_env_file = "host.env";
+        extract($config);
+
+        $composer
+            ->addService("pma")
+            ->image("phpmyadmin/phpmyadmin")
+            ->restart($this->_docker_restart_default)
+            ->addLinks("mysql", "mysql")
+            ->addEnv_file("host.env")
+            ->addEnv_file("mysql." . $host_env_file)
+            ->addEnv_file($module . "." . $host_env_file)
+            ->addVolumes("pma_volumen", "/www");
+
+        $this->writeVariablesEnviroment($module . "." . $host_env_file, $module);
+    }
+
+    function addGrafana(FileFormat2 $composer, $config = array())
+    {
+        $module = "grafana";
+        $host_env_file = "";
+        extract($config);
+
+        $composer
+            ->addService($module)
+            ->image("grafana/grafana:5.0.4")
+            ->addLinks("mysql")
+            ->restart($this->_docker_restart_default)
+            ->addEnv_file("running.env")
+            ->addEnv_file("grafana.env")
+            ->addVolumes("./extra/statsd/grafana/lib", "/var/lib/grafana");
+
+        $this->addJsonEndPoints($composer, $config);
+
+    }
+
+    function addJsonEndPoints(FileFormat2 $composer, $config = array())
+    {
+        $version = "latest";
+        $registry = "";
+        $host_env_file = "";
+        extract($config);
+        $composer
+            ->addService("statsd")
+            ->image($registry . "fd3/statsd:$version")
+            ->addPorts("8125", "8125/udp")
+            ->addLinks("mysql")
+            ->addLinks("mongodb")
+            ->restart($this->_docker_restart_default)
+            ->addVolumes("./extra/statsd/statsd/statsd.config.js", "/opt/config/statsd.config.js");
+
+        $composer
+            ->addService("jsendpoint")
+            ->image($registry . "fd3/jsonep:$version")
+            ->addVolumes("./extra/statsd/endpoint/json", "/opt/datasource")
+            ->addLinks("jsonep_mysql")
+            ->addLinks("jsonep_mongo")
+            ->restart($this->_docker_restart_default);
+
+        $composer
+            ->addService("jsonep_mysql")
+            ->image($registry . "fd3/jsonep_mysql:$version")
+            ->addVolumes("./extra/statsd/endpoint/mysql", "/opt/datasource")
+            ->addLinks("mysql")
+            ->addEnv_file("mysql." . $host_env_file)
+            ->restart($this->_docker_restart_default);
+
+        $composer
+            ->addService("jsonep_mongo")
+            ->image($registry . "fd3/jsonep_mongo:$version")
+            ->addVolumes("./extra/statsd/endpoint/mongodb", "/opt/datasource")
+            ->addLinks("mongodb")
+            ->restart($this->_docker_restart_default);
+    }
+    
+    public function commandWorkerAux($worker, $module, $consumer, FileFormat2 $composer, $config = array())
+    {
+        $version = "latest";
+        $registry = "";
+        extract($config);
+
+        return $composer
+            ->addService($worker)
+            ->image("{$registry}fd3/{$module}:{$version}")
+            ->command("bin/console rabbitmq:consumer {$consumer}")
+            
+            ->restart($this->_docker_restart_default)
+            ->addLinks("mysql")
+            ->addLinks("base")
+            ->addLinks("nginx", $this->getDomain("base"))
+            ->addEnv_file("running.env")
+            ->addEnv_file("host.env")
+            
+            ->addEnv_file("{$module}.host.env")
+            ->addEnviroment("AMQP_KEY", $module)
+            ->addVolumes("{$module}_volumen", "/opt/{$module}")
+            ;
+    }
+
+    function addCommandWorkers(FileFormat2 $composer, $config = array())
+    {
+        $version = "latest";
+        $registry = "";
+        extract($config);
+        
+        $service = $this->commandWorkerAux('base_log_worker', 'base', 'log_consumer', $composer, $config);
+        
+        $service
+            ->addEnviroment("SYMFONY_ENV", "prod")
+            ;
+            
+        $service = $this->commandWorkerAux('ftth_tasklogger_worker', 'ftth', 'flowdat_tasklogger', $composer, $config);
+            
+        $service
+         ->addVolumes("./extra/netmiko", "/opt/netmiko")
+         ->addVolumes("./extra/backups-config", "/opt/ftth/web/backups-config");
+        
+        $service = $this->commandWorkerAux('cablemodem_tasklogger_worker', 'cablemodem', 'flowdat_tasklogger', $composer, $config); 
+         
+        $service = $this->commandWorkerAux('dhcp_tasklogger_worker', 'dhcp', 'flowdat_tasklogger', $composer, $config); 
+            
+        $service = $this->commandWorkerAux('ftth_command_worker', 'ftth', 'command_consumer', $composer, $config); 
+        
+        $service = $this->commandWorkerAux('stats_command_worker', 'stats', 'command_consumer', $composer, $config); 
+        
+        $service
+            ->addLinks("geoserver")
+            ->addLinks("nginx", $this->getDomain("geoserver"))
+            // ->addVolumes("./geoserver/geoserver-shapes", "/var/www/shapes")
+            ->addVolumes("geoserver_volumen", "/var/www/shapes");
+            
+        $service = $this->commandWorkerAux('cablemodem_command_worker', 'cablemodem', 'command_consumer', $composer, $config);
+    }
+
+    /**
+     * @param FileFormat2 $composer
+     * @param array $config
+     */
+    public function addGeoserver(FileFormat2 $composer, $config = array())
+    {
+        $version = "latest";
+        $registry = "";
+        extract($config);
+
+        $composer
+            ->addService("geoserver")
+            ->image($registry . "fd3/geoserver:" . $version)
+            ->restart($this->_docker_restart_default)
+            ->addLinks("nginx", $this->getDomain("geoserver"))
+            ->addEnv_file("running.env")
+            ->addEnv_file("host.env")
+            ->addVolumes("./extra/geoserver/geoserver-data/styles", "/opt/geoserver/data_dir/styles")
+            ->addVolumes("geoserver_volumen", "/var/www/shapes")
+            // ->addVolumes("./geoserver/geoserver-shapes", "/var/www/shapes")
+            ->addPorts(8081, 8080)
+            ->mem_limit('500m');
+    }
+
+    /**
+     * @param FileFormat2 $composer
+     * @param array $config
+     */
+    public function addKea(FileFormat2 $composer, $config = array())
+    {
+        $version = "latest";
+        $registry = "";
+        extract($config);
+
+        $module = 'kea';
+        $composer
+            ->addService("kea")
+            ->image($registry . "fd3/kea-ik-1.4.0:" . $version)
+            ->restart($this->_docker_restart_default)
+            ->addPorts(8086, 8080)
+            ->addPorts(67, '67/udp')
+            ->addPorts(68, '68/udp')
+            ->addEnv_file("running.env")
+            ->addEnv_file("host.env")
+            ->addEnv_file($module . "." . $host_env_file)
+            ->addVolumes("kea_volumen", "/usr/local/etc/kea")
+            // ->addVolumes("kea_ctrl_agent_volumen", "/usr/local/etc/kea/kea-ctrl-agent.conf")
+            // ->addVolumes("kea_dhcp4_volumen", "/usr/local/etc/kea/kea-dhcp4.conf")
+            // ->addVolumes("kea_supervisord_volumen", "/etc/supervisord")
+            // ->addVolumes("kea_hooks_volumen", "/opt/hooks")
+            ->addVolumes("./kea/conf/kea-ctrl-agent.conf", "/usr/local/etc/kea/kea-ctrl-agent.conf")
+            ->addVolumes("./kea/conf/kea-dhcp4.conf", "/usr/local/etc/kea/kea-dhcp4.conf")
+            ->addVolumes("./kea/supervisord", "/etc/supervisord")
+            ->addVolumes("./kea/hooks", "/opt/hooks")
+            ;
+        $this->writeVariablesEnviroment($module . "." . $host_env_file, $module,
+            array(
+                "MYSQL_ROOT_PASSWORD" => $this->_mysql_root_pass,
+                "MYSQL_USER" => $this->_mysql_user,
+            ));
+    }
+
+     /**
+     * @param FileFormat2 $composer
+     * @param array $config
+     */
+    public function addSwagger(FileFormat2 $composer, $config = array())
+    {
+        $version = "latest";
+        $registry = "";
+        extract($config);
+
+        $composer
+            ->addService("swagger-ui")
+            ->image($registry . "fd3/swagger-ui:" . $version)
+            ->restart($this->_docker_restart_default)
+            ->addEnviroment("SWAGGER_JSON", "/opt/api/api.v1.json")
+            ->addEnv_file("running.env")
+            ->addEnv_file("host.env")
+            ->addPorts(8090, 8080);
+    }
+
+}