Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
meltmedia/meltconsole / src / App / Commands / RemoveEnvironmentCommand.php
Size: Mime:
<?php

namespace MeltConsole\App\Commands;

use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\ConfirmationQuestion;

/**
 * Handles functionality to remove environments from server.
 *
 * @package MeltConsole\App\Commands
 */
class RemoveEnvironmentCommand extends MeltCommand {

  /**
   * Environments to exclude from removal.
   *
   * If these need to be removed, then that should be done on the server.
   *
   * @var array
   */
  private $excludedEnvs = ['dev', 'qa', 'stage', 'uat', 'prod'];

  /**
   * {@inheritdoc}
   */
  protected function configure() {

    // Initial config for command.
    $this
      ->setName('melt:remove-environment')
      ->setAliases(['melt:re'])
      ->setDescription('Removes environment on the remote server.')
      ->setHelp('This command allows you to remove an environment...')
      ->addOption('env', 'e', InputOption::VALUE_REQUIRED, 'Environment e.g dev, qa, stage');
  }

  /**
   * {@inheritdoc}
   */
  protected function interact(InputInterface $input, OutputInterface $output) {
    parent::interact($input, $output);

    if (!$input->getOption('env')) {
      $current_envs = $this->getEnvironmentsFromServer();

      if (!empty($current_envs)) {

        // Ask the user if their 100% sure they want to create the environment.
        $output->writeln([
          '-----------------------------',
          '           NOTICE',
          '-----------------------------',
          'FYI, we won\'t actually remove the environment immediately.',
          'We\'ll first create a backup of the database and files and store them',
          'at in the <info>/opt/backups</info> directory in case we need to restore.',
          '-----------------------------',
        ]);

        // Ask the user some stuff.
        $helper = $this->getHelper('question');
        $question = new ChoiceQuestion('Choose the environment you\'d like to slaughter!', $current_envs);
        $env = $helper->ask($input, $output, $question);

        if (empty($env)) {
          throw new LogicException('Please enter a value for environment name.');
        }

        if (in_array($env, $this->excludedEnvs)) {
          throw new LogicException("The {$env} environment can not be removed by {$this->appName}. The environment should be removed on the server.");
        }

        // Set options based on users answer.
        $input->setOption('env', $env);
      }
      else {
        throw new LogicException('There are no environments available for removal.');
      }

    }

  }

  /**
   * {@inheritdoc}
   */
  protected function execute(InputInterface $input, OutputInterface $output) {

    $env = $input->getOption('env');
    if ($this->validateEnvironmentExistsOnServer($env)) {
      $dirname = "{$this->projectName}-{$env}";
      $helper = $this->getHelper('question');
      $question = new ConfirmationQuestion(sprintf(
        'Exterminate <info>%s</info> environment? (y/N)',
        $dirname
      ), FALSE);

      if ($helper->ask($input, $output, $question)) {

        // Remove env from server.
        $output->writeln('Exterimination in progress...');
        $this->removeEnvironment($env);
        $output->writeln("{$dirname} environment has been exterminated! Muhahahaha!!");

        if ($this->environmentHasDrushAlias($env)) {
          $output->writeln("To be nice, I'm also going to annihilate the drush alias for <info>${dirname}</info>...");
          $this->removeDrushAlias($env);
          $output->writeln("BOOM! alias has been annihilated from <info>{$this->pathToDrushAlias}</info>!!!");
        }
      }

    }
    else {
      throw new LogicException(sprintf(
        'Whaaaaa??? It appears the %s environment doesn\'t exists on the server. Skipping.',
        $env
      ));
    }
  }

  /**
   * Create's new directory on server by cloning the git repo.
   *
   * @param string $env
   *   Directory name.
   */
  protected function removeEnvironment(string $env) {
    $projectName = "{$this->projectName}-{$env}";
    $timestamp = date('Ymdhi');
    $backup_name = "{$projectName}-{$timestamp}";
    $backup_dir = '/opt/backups';
    $filesDir = 'docroot/sites/default/files/';
    $dbName = str_replace('-', '_', $projectName);
    $dbUser = $this->getServerEnvVar('MELT_DB_USER');
    $dbPass = $this->getServerEnvVar('MELT_DB_PASS');


    // Backup files
    $this->runServerCommands([
      // Change into src directory.
      "cd /{$this->serverRoot}/{$projectName}",

      // Make sure `files` dir exists before rsyncing
      "[ -d {$filesDir} ]", // Make sure `files` dir exists before rsyncing

      // Zip `docroot/sites/default/files` and move to backup directory
      "tar -czf {$backup_dir}/{$backup_name}.tar.gz {$filesDir}",
    ]);

    // Backup database
    $this->runServerCommands([
      // Change into src directory.
      "cd /{$this->serverRoot}/{$projectName}",

      // Add to backups directory
      "drush sql:dump --gzip --result-file={$backup_dir}/{$backup_name}.sql",
    ]);


    // Time to remove files related to environment
    $this->runServerCommands([

      // Remove SSL config
      "sudo rm /etc/nginx/ssl/ssl_{$projectName}.conf",

      // Remove nginx sites-available config
      "sudo rm /etc/nginx/sites-available/{$projectName}",

      // Remove nginx sites-enabled symbolic link
      "sudo rm /etc/nginx/sites-enabled/{$projectName}",

      // Drop database
      "sudo mysql -u{$dbUser} -p{$dbPass} -e 'DROP DATABASE {$dbName}'",

      // Remove project directory
      "sudo rm -rf /{$this->serverRoot}/{$projectName}",

      // Test nginx
      'sudo nginx -t',

      // Reload nginx
      'sudo systemctl reload nginx',

      // Reload php
      'sudo systemctl reload php7.2-fpm'
    ]);

  }

  /**
   * Removes drush alias from @var $pathToDrushAlias.
   *
   * @param string $env
   *   Environment name.
   */
  protected function removeDrushAlias(string $env) {
    $aliases = $this->getDrushAliases();

    if (isset($aliases[$env])) {

      // Delete alias.
      unset($aliases[$env]);

      // Create a YAML string to pass off to our @var $pathToDrushAlias.
      $this->writeToYamlFile($aliases, $this->pathToDrushAlias);
    }
    else {
      $this->logger->log('warning', 'No alias not found to remove. Skipping.');
    }

  }

}