* Implemented ScriptRunner with environment expansion and cleaner code. * Added ApiClient plugin (com.noccy.apiclient) * Renamed CHANGELOG.md to VERSIONS.md * Shuffled buildtools * Added first unittests
		
			
				
	
	
		
			90 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace SparkPlug\Com\Noccy\Docker;
 | 
						|
 | 
						|
use Spark\Commands\Command;
 | 
						|
use SparkPlug;
 | 
						|
use Symfony\Component\Console\Input\Input;
 | 
						|
use Symfony\Component\Console\Input\InputInterface;
 | 
						|
use Symfony\Component\Console\Input\InputOption;
 | 
						|
use Symfony\Component\Console\Output\OutputInterface;
 | 
						|
 | 
						|
class DockerDbExportCommand extends Command
 | 
						|
{
 | 
						|
    protected function configure()
 | 
						|
    {
 | 
						|
        $this->setName("docker:db:export")
 | 
						|
            ->setDescription("Export a database")
 | 
						|
            ->addOption("mysql", null, InputOption::VALUE_NONE, "Export from a MySQL database")
 | 
						|
            ->addOption("dsn", null, InputOption::VALUE_REQUIRED, "Database DSN")
 | 
						|
            ->addOption("service", null, InputOption::VALUE_REQUIRED, "Service name in stack")
 | 
						|
            ->addOption("database", null, InputOption::VALUE_REQUIRED, "Database name")
 | 
						|
            ->addOption("output", "o", InputOption::VALUE_REQUIRED, "Output to file instead of stdout")
 | 
						|
            ;
 | 
						|
    }
 | 
						|
 | 
						|
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
						|
    {
 | 
						|
        $docker = get_plugin("com.noccy.docker");
 | 
						|
 | 
						|
        $service = $input->getOption("service");
 | 
						|
        $dsn = $input->getOption("dsn");
 | 
						|
        if ($service) {
 | 
						|
            $stack = $docker->getComposeStack();
 | 
						|
            if ($input->getOption("mysql")) {
 | 
						|
                $dbtype = 'mysql';
 | 
						|
            } else {
 | 
						|
                $services = $stack->getServiceNames();
 | 
						|
                if (!in_array($service, $services)) {
 | 
						|
                    $output->writeln("<error>Invalid service {$service}. Valid are ".join(", ", $services)."</>");
 | 
						|
                    return Command::INVALID;
 | 
						|
                }
 | 
						|
                $image = $stack->getService($service)->getImage();
 | 
						|
                if (preg_match('/(mysql|mariadb)/i', $image)) {
 | 
						|
                    $dbtype = 'mysql';
 | 
						|
                    $env = $stack->getService($service)->getEnvironment();
 | 
						|
                    $database = $env['MYSQL_DATABASE']??null;
 | 
						|
                    if ($dbpass = $env['MYSQL_ROOT_PASSWORD']??null) {
 | 
						|
                        $dbuser = 'root';
 | 
						|
                    } else {
 | 
						|
                        $dbuser = $env['MYSQL_USER']??null;
 | 
						|
                        $dbpass = $env['MYSQL_PASSWORD']??null;
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    $output->writeln("<error>Unable to determine database type from service</>");
 | 
						|
                    return Command::INVALID;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            $database = $database ?? $input->getOption("database");
 | 
						|
            if (empty($database)) {
 | 
						|
                $output->writeln("<error>No --database specified</>");
 | 
						|
                return Command::INVALID;
 | 
						|
            }
 | 
						|
            switch ($dbtype) {
 | 
						|
                case 'mysql':
 | 
						|
                    $cmd = sprintf("mysqldump -u%s -p%s %s", $dbuser, $dbpass, $database);
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
            $this->exportFromService($service, $cmd, $output, $input->getOption("output"));
 | 
						|
        } elseif ($dsn) {
 | 
						|
            $url = parse_url($dsn);
 | 
						|
            if (empty($url)) {
 | 
						|
                $output->writeln("<error>Bad database DSN {$dsn}. Should look like mysql://user:pass@host:port/database</>");
 | 
						|
                return Command::INVALID;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return Command::SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    private function exportFromService(string $service, string $command, OutputInterface $output, ?string $outfile=null)
 | 
						|
    {
 | 
						|
        $cmd = sprintf("docker-compose exec -T %s %s", $service, $command);
 | 
						|
        if ($outfile) {
 | 
						|
            $cmd .= " > ".escapeshellarg($outfile);
 | 
						|
        }
 | 
						|
        $output->writeln(sprintf("→ <info>%s</>", $cmd));
 | 
						|
        passthru($cmd);
 | 
						|
    }
 | 
						|
}
 |