/** * @throws \Exception */ public function run() { if (!$this->command instanceof ProvisionCommand) { throw new \Exception("The ConfigDefaults task can only be run by the Provision command."); } $fs = Util::getFilesystem(); $config_files = SyncManager::getRules(SyncManager::SYNC_FILE); $config_dirs = SyncManager::getRules(SyncManager::SYNC_DIR); $config_sources = array_merge(array_column($config_files, 'source'), array_column($config_dirs, 'source')); if ($fs->exists($config_sources)) { return; } $config_sources_dirs = []; foreach ($config_sources as $config_source) { $config_source_dir = dirname($config_source); while ($config_source_dir != '/vagrant' && !in_array($config_source_dir, $config_sources_dirs)) { $config_sources_dirs[] = $config_source_dir; $config_source_dir = dirname($config_source_dir); } } $fs->mkdir($config_sources_dirs, 0777, 'vagrant'); foreach ($config_files as $file) { if (empty($file['default'])) { continue; } $target_file = $file['source']; $origin_file = $file['default']; if (!file_exists($target_file)) { $this->output->writeInfo("Writing default config file '{$target_file}'"); $fs->copy($origin_file, $target_file, true, 'vagrant'); } } foreach ($config_dirs as $dir) { if (empty($dir['default'])) { continue; } $source_dir = $dir['default']; $target_dir = $dir['source']; if (file_exists($target_dir)) { continue; } $this->output->writeInfo("Writing default config dir '{$target_dir}'"); $fs->mkdir($target_dir, 0777, 'vagrant'); $finder = new Finder(); foreach ($finder->files()->in($source_dir)->ignoreDotFiles(false)->depth('== 0') as $origin_dir_file) { $origin_dir_filename = $origin_dir_file->getFilename(); $target_dir_filepath = $target_dir . '/' . $origin_dir_filename; $origin_dir_filepath = $source_dir . '/' . $origin_dir_filename; $fs->copy($origin_dir_filepath, $target_dir_filepath, true, 'vagrant'); } } }
/** * Manages php builds via phpbrew * * @param $meta * @throws \Exception */ protected function managePhp($meta) { $fs = Util::getFilesystem(); if (!$meta['installed']) { $this->output->writeInfo("Removing php {$meta['_build']}"); // php fpm has to be stopped before remving php build so that // the php-fpm.pid file is still exist $this->stopFpm($meta['_build']); $proc = $this->runScript('php.remove', $meta['_build']); if ($proc->isSuccessful()) { $this->output->writeInfo("Successfully removed php"); } else { throw new \Exception("Unable to remove php"); } SyncManager::removeRule($meta['_path'], true, true); $fs->remove($meta['_path']); return; } else { $this->output->writeInfo("Checking php {$meta['_build']}"); } if (!isset($meta['version'])) { $meta['version'] = $meta['_build']; } if (!empty($meta['_old']) && !isset($meta['_old']['version'])) { $meta['_old']['version'] = $meta['_build']; } if (!preg_match('/^[0-9][0-9\\.]*[0-9]$/', $meta['version'])) { throw new \Exception("Invalid php version {$meta['version']}"); } if (version_compare($meta['version'], '5.3.0') < 0) { throw new \Exception("Building php versions older than 5.3.0 is not supported"); } if (empty($meta['variants'])) { throw new \Exception("Build variants for php {$meta['_build']} are not defined in environment.yaml file"); } if (!is_array($meta['variants'])) { $meta['variants'] = [$meta['variants']]; } if (!empty($meta['_old']) && !is_array($meta['_old']['variants'])) { $meta['_old']['variants'] = [$meta['_old']['variants']]; } if ($meta['_is_installed'] && !empty($meta['_old']) && $meta['_old']['version'] == $meta['version'] && $meta['_old']['variants'] == $meta['variants']) { return; } $this->output->writeInfo("Building php from source"); $this->output->writeInfo("This may take a while depending on your cpu(s)..."); foreach ($meta['variants'] as $i => $variant) { if (false === strpos($variant, '--', 0)) { $meta['variants'][$i] = '+' . $variant; } } // stop php-fpm if we are rebuilding php if ($meta['_is_installed']) { $this->stopFpm($meta['_build']); } $proc = $this->runScript('php.install', $meta['_build'], $meta['version'], implode(" ", $meta['variants'])); if ($proc->isSuccessful() && file_exists($meta['_path'] . '/bin/php')) { // we need this directory to be available right after successfull build // since phpbrew doesn't make this directory by default $fs->mkdir($meta['_path'] . '/var/db', 0755, 'vagrant'); $this->output->writeInfo("Successfully built php"); // Get a copy of the log file $log_from = "/opt/phpbrew/build/{$meta['_build']}/build.log"; $log_to = "/vagrant/provision/main/logs/phpbuild-{$meta['_build']}.log"; $fs->copy($log_from, $log_to, true); $this->output->writeInfo("Saved build log file to {$log_to}"); } else { $fs->remove($meta['_path']); throw new \Exception("Unable to build php"); } // @todo fix code duplication issue since this code is already defined in initTask if (!$meta['_is_installed']) { SyncManager::addRule(SyncManager::SYNC_FILE, ['path' => "/opt/phpbrew/php/{$meta['_build']}/etc/php.ini", 'source' => "/vagrant/config/phpbrew/{$meta['_build']}/php.ini", 'default' => "/opt/phpbrew/php/{$meta['_build']}/etc/php.ini", 'owner' => 'vagrant', 'group' => 'vagrant']); SyncManager::addRule(SyncManager::SYNC_FILE, ['path' => "/opt/phpbrew/php/{$meta['_build']}/etc/php-fpm.conf", 'source' => "/vagrant/config/phpbrew/{$meta['_build']}/php-fpm.conf", 'default' => "/opt/phpbrew/php/{$meta['_build']}/etc/php-fpm.conf", 'owner' => 'vagrant', 'group' => 'vagrant']); SyncManager::addRule(SyncManager::SYNC_DIR, ['path' => "/opt/phpbrew/php/{$meta['_build']}/var/db", 'source' => "/vagrant/config/phpbrew/{$meta['_build']}/conf.d", 'default' => "/opt/phpbrew/php/{$meta['_build']}/var/db", 'owner' => 'vagrant', 'group' => 'vagrant']); } }
/** * Syncs directories files between the host and guest using bi-directional sync algorithm */ protected function syncDirs() { $fs = Util::getFilesystem(); $sync_status = []; if (file_exists(self::SYNC_STATUS_FILE)) { $sync_status = json_decode(file_get_contents(self::SYNC_STATUS_FILE), true); } $sync_status_new = []; $config_dirs = SyncManager::getRules(SyncManager::SYNC_DIR); foreach ($config_dirs as $dir) { if (empty($dir['path'])) { continue; } $source_dir = $dir['source']; $source_dir_owner = 'vagrant'; $source_dir_group = 'vagrant'; $target_dir = $dir['path']; $target_dir_owner = !empty($dir['owner']) ? $dir['owner'] : null; $target_dir_group = !empty($dir['group']) ? $dir['group'] : null; if ($source_dir == $target_dir) { continue; } $dir_sync_status = ['old' => [], 'new' => []]; if (isset($sync_status[$target_dir])) { $dir_sync_status['old'] = $sync_status[$target_dir]; } $finder = new Finder(); foreach ($finder->files()->in($source_dir)->ignoreDotFiles(false)->depth('== 0') as $source_dir_file) { $source_dir_filename = $source_dir_file->getFilename(); $source_dir_filepath = $source_dir . '/' . $source_dir_filename; $target_dir_filepath = $target_dir . '/' . $source_dir_filename; // Sync file changes if (file_exists($target_dir_filepath)) { $dir_sync_status['new'][] = $source_dir_filename; if (md5_file($source_dir_filepath) === md5_file($target_dir_filepath)) { continue; } $source_dir_filetime = filemtime($source_dir_filepath); $target_dir_filetime = filemtime($target_dir_filepath); if ($source_dir_filetime >= $target_dir_filetime) { $copy_from = $source_dir_filepath; $copy_to = $target_dir_filepath; $copy_owner = $target_dir_owner; $copy_group = $target_dir_group; } else { $copy_from = $target_dir_filepath; $copy_to = $source_dir_filepath; $copy_owner = $source_dir_owner; $copy_group = $source_dir_group; } $this->output->writeInfo("Syncing config file '{$source_dir_filepath}' " . ($copy_from == $source_dir_filepath ? "->" : "<-") . " '{$target_dir_filepath}'"); $fs->copy($copy_from, $copy_to, true, $copy_owner, $copy_group); } else { if (in_array($source_dir_filename, $dir_sync_status['old'])) { $this->output->writeInfo("Removing config file '{$source_dir_filepath}'"); $fs->remove($source_dir_filepath); } else { $dir_sync_status['new'][] = $source_dir_filename; $this->output->writeInfo("Copying config file '{$source_dir_filepath}' -> '{$target_dir_filepath}'"); $fs->copy($source_dir_filepath, $target_dir_filepath, true, $target_dir_owner, $target_dir_group); } } } $finder = new Finder(); foreach ($finder->files()->in($target_dir)->ignoreDotFiles(false)->depth('== 0') as $target_dir_file) { $target_dir_filename = $target_dir_file->getFilename(); $source_dir_filepath = $source_dir . '/' . $target_dir_filename; $target_dir_filepath = $target_dir . '/' . $target_dir_filename; if (in_array($target_dir_filename, $dir_sync_status['new'])) { continue; } // Delete file from target dir if (in_array($target_dir_filename, $dir_sync_status['old'])) { $this->output->writeInfo("Removing config file '{$target_dir_filepath}'"); $fs->remove($target_dir_filepath); } else { $this->output->writeInfo("Copying config file '{$source_dir_filepath}' <- '{$target_dir_filepath}'"); $fs->copy($target_dir_filepath, $source_dir_filepath, true, $source_dir_owner, $source_dir_group); $dir_sync_status['new'][] = $target_dir_filename; } } $sync_status_new[$target_dir] = $dir_sync_status['new']; } // Write status file $this->output->writeDebug("Writing config directories sync status file"); $fs->write(self::SYNC_STATUS_FILE, json_encode($sync_status_new), 'vagrant'); }
/** * @throws \Exception */ public function run() { if (!$this->command instanceof ProvisionCommand) { throw new \Exception("The Init task can only be run by the Provision command."); } // Check box version if (!file_exists('/etc/dashbrew/.version')) { throw new \Exception("Unable to find base box version file."); } $box_version = file_get_contents('/etc/dashbrew/.version'); if (empty($box_version)) { throw new \Exception("Invalid base box version file."); } if (false === strpos($box_version, DASHBREW_BASEBOX_VERSION, 0)) { throw new \Exception("Incompatible base box version ({$box_version}). Dashbrew requires a base box version " . DASHBREW_BASEBOX_VERSION . ".x"); } $this->output->writeDebug("Checking for available " . $box_version . " patches"); $box_patch_file = '/etc/dashbrew/.patch'; $box_patch_md5 = null; if (file_exists($box_patch_file)) { $box_patch_md5 = file_get_contents($box_patch_file); } $available_patch = file_get_contents('https://raw.githubusercontent.com/mdkholy/dashbrew-basebox/master/patches/' . $box_version . '.sh'); $apply_patch = false; if (!empty($available_patch)) { $available_patch_md5 = md5($available_patch); if ($box_patch_md5 != $available_patch_md5) { $apply_patch = true; } } if ($apply_patch) { $this->output->writeInfo("An update patch is available for your box. Updating..."); $fs = Util::getFilesystem(); $exec_patch_file = '/tmp/dashbrew-basebox-patch.sh'; $fs->write($exec_patch_file, $available_patch, 'root'); $fs->chmod($exec_patch_file, 0755); $proc = Util::Process($this->output, "sudo bash {$exec_patch_file}", ['timeout' => null]); if ($proc->isSuccessful()) { $this->output->writeInfo("Update patch has been applied successfully"); } else { $this->output->writeError("Error occured while applying update patch"); } $fs->remove($exec_patch_file); $fs->write($box_patch_file, $available_patch_md5); $fs->chmod($box_patch_file, 0644); } // Parse & initialize config.yaml file if (file_exists(Config::CONFIG_FILE)) { $this->output->writeInfo("Initializing environment.yaml"); } else { $this->output->writeInfo("Provisioning without environment.yaml config file"); } Config::init(); if (Config::get('debug')) { $this->output->setVerbosity(Output::VERBOSITY_DEBUG); } // Initialize config files and directories $this->output->writeDebug("Initializing config files"); $config_files = [['path' => '/etc/monit/monitrc', 'source' => '/vagrant/config/monit/monitrc', 'default' => '/etc/monit/monitrc', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/apache2/apache2.conf', 'source' => '/vagrant/config/apache/apache.conf', 'default' => '/etc/apache2/apache2.conf', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/php5/fpm/php-fpm.conf', 'source' => '/vagrant/config/php/fpm/php-fpm.conf', 'default' => '/etc/php5/fpm/php-fpm.conf', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/php5/fpm/php.ini', 'source' => '/vagrant/config/php/fpm/php.ini', 'default' => '/etc/php5/fpm/php.ini', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/mysql/my.cnf', 'source' => '/vagrant/config/mysql/my.cnf', 'default' => '/etc/mysql/my.cnf', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/php5/cli/php.ini', 'source' => '/vagrant/config/php/cli/php.ini', 'default' => '/etc/php5/cli/php.ini', 'owner' => 'root', 'group' => 'root'], ['path' => '/opt/phpbrew/config.yaml', 'source' => '/vagrant/config/phpbrew/config.yaml', 'default' => '/opt/phpbrew/config.yaml', 'owner' => 'vagrant', 'group' => 'vagrant'], ['path' => '/usr/share/phpmyadmin/config.inc.php', 'source' => '/vagrant/config/phpmyadmin/config.inc.php', 'default' => '/usr/share/phpmyadmin/config.inc.php', 'owner' => 'vagrant', 'group' => 'www-data']]; $config_dirs = [['path' => '/home/vagrant', 'source' => '/vagrant/config/home', 'default' => '/home/vagrant', 'owner' => 'vagrant', 'group' => 'vagrant'], ['path' => '/etc/monit/conf.d', 'source' => '/vagrant/config/monit/conf.d', 'default' => '/etc/monit/conf.d', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/php5/cli/conf.d', 'source' => '/vagrant/config/php/cli/conf.d', 'default' => '/etc/php5/cli/conf.d', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/php5/fpm/conf.d', 'source' => '/vagrant/config/php/fpm/conf.d', 'default' => '/etc/php5/fpm/conf.d', 'owner' => 'root', 'group' => 'root'], ['path' => '/etc/php5/fpm/pool.d', 'source' => '/vagrant/config/php/fpm/pool.d', 'default' => '/etc/php5/fpm/pool.d', 'owner' => 'root', 'group' => 'root']]; $installed_phps = Util::getInstalledPhps(); $phps = Config::get('php::builds'); foreach ($phps as $build => $meta) { if (!in_array($build, $installed_phps)) { continue; } $config_dirs[] = ['path' => "/opt/phpbrew/php/{$build}/var/db", 'source' => "/vagrant/config/phpbrew/{$build}/conf.d", 'default' => "/opt/phpbrew/php/{$build}/var/db", 'owner' => 'vagrant', 'group' => 'vagrant']; $config_files[] = ['path' => "/opt/phpbrew/php/{$build}/etc/php.ini", 'source' => "/vagrant/config/phpbrew/{$build}/php.ini", 'default' => "/opt/phpbrew/php/{$build}/etc/php.ini", 'owner' => 'vagrant', 'group' => 'vagrant']; $config_files[] = ['path' => "/opt/phpbrew/php/{$build}/etc/php-fpm.conf", 'source' => "/vagrant/config/phpbrew/{$build}/php-fpm.conf", 'default' => "/opt/phpbrew/php/{$build}/etc/php-fpm.conf", 'owner' => 'vagrant', 'group' => 'vagrant']; } foreach ($config_files as $config_file) { SyncManager::addRule(SyncManager::SYNC_FILE, $config_file); } foreach ($config_dirs as $config_dir) { SyncManager::addRule(SyncManager::SYNC_DIR, $config_dir); } $services = ['apache', 'mysql', 'php-system-fpm', 'mailcatcher']; foreach ($services as $service) { ServiceManager::addService($service); } }