132 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			132 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace NoccyLabs\Serverctl\Container;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ContainerManager
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private string $dataPath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function __construct(?string $dataPath=null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->dataPath = $dataPath ?? (getenv("HOME")."/.var/serverctl");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Start a service
							 | 
						||
| 
								 | 
							
								     * 
							 | 
						||
| 
								 | 
							
								     * Instance options:
							 | 
						||
| 
								 | 
							
								     *   name: Instance name (default)
							 | 
						||
| 
								 | 
							
								     *   portoffset: Port number offset (0)
							 | 
						||
| 
								 | 
							
								     * 
							 | 
						||
| 
								 | 
							
								     * @param array $service The service definition from the registry  
							 | 
						||
| 
								 | 
							
								     * @param array $options Instance options
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function startService(array $service, array $options)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $args = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $serviceName = $service['name'];
							 | 
						||
| 
								 | 
							
								        $instanceName = $options['name']??'default';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $containerName = "sm_".$serviceName."_".$instanceName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $args[] = 'run';
							 | 
						||
| 
								 | 
							
								        $args[] = '--rm'; // remove container after run
							 | 
						||
| 
								 | 
							
								        $args[] = '-d';
							 | 
						||
| 
								 | 
							
								        $args[] = '--name';
							 | 
						||
| 
								 | 
							
								        $args[] = $containerName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Map the ports
							 | 
						||
| 
								 | 
							
								        $ports = (array)($service['ports']??[]);
							 | 
						||
| 
								 | 
							
								        foreach ($ports as $port) {
							 | 
						||
| 
								 | 
							
								            $args[] = '-p';
							 | 
						||
| 
								 | 
							
								            $args[] = $port['port'];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Get the paths to persist
							 | 
						||
| 
								 | 
							
								        $volumes = (array)($service['persistence']??[]);
							 | 
						||
| 
								 | 
							
								        $volumePath = $this->getServiceDataPath($service)."/".$instanceName;
							 | 
						||
| 
								 | 
							
								        foreach ($volumes as $volume) {
							 | 
						||
| 
								 | 
							
								            // volume { path, hint }
							 | 
						||
| 
								 | 
							
								            $path = $volume['path'];
							 | 
						||
| 
								 | 
							
								            $hint = $volume['hint'] ?? crc32($path);
							 | 
						||
| 
								 | 
							
								            $args[] = '-v'; // add volume
							 | 
						||
| 
								 | 
							
								            $args[] = $volumePath."/".$hint.":".$path;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Get environment
							 | 
						||
| 
								 | 
							
								        $envs = (array)($service['environment']??[]);
							 | 
						||
| 
								 | 
							
								        foreach ($envs as $env=>$value) {
							 | 
						||
| 
								 | 
							
								            $args[] = '-e';
							 | 
						||
| 
								 | 
							
								            // TODO: use environment if set (override)
							 | 
						||
| 
								 | 
							
								            $args[] = sprintf("%s=%s", $env, $value);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $args[] = $service['image'];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $cmdl = 'docker '.join(' ',array_map('escapeshellarg', $args));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // TODO: Write command line, env and meta to state file
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        echo "$ {$cmdl}\n";
							 | 
						||
| 
								 | 
							
								        passthru($cmdl);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Stop a service
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function stopService(array $service, string $instanceName)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $args = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $serviceName = $service['name'];
							 | 
						||
| 
								 | 
							
								        $instanceName = $options['name']??'default';
							 | 
						||
| 
								 | 
							
								        $containerName = "sm_".$serviceName."_".$instanceName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $args[] = 'stop';
							 | 
						||
| 
								 | 
							
								        $args[] = $containerName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $cmdl = 'docker '.join(' ',array_map('escapeshellarg', $args));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        echo "$ {$cmdl}\n";
							 | 
						||
| 
								 | 
							
								        passthru($cmdl);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function execute(array $service, string $instanceName, array $command)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $args = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $serviceName = $service['name'];
							 | 
						||
| 
								 | 
							
								        $instanceName = $options['name']??'default';
							 | 
						||
| 
								 | 
							
								        $containerName = "sm_".$serviceName."_".$instanceName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $args[] = 'exec';
							 | 
						||
| 
								 | 
							
								        $args[] = '-it';
							 | 
						||
| 
								 | 
							
								        $args[] = $containerName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        array_push($args, ...$command);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $cmdl = 'docker '.join(' ',array_map('escapeshellarg', $args));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        echo "$ {$cmdl}\n";
							 | 
						||
| 
								 | 
							
								        passthru($cmdl);
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Get running services
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function getRunningServices(): array
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return [];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function getServiceDataPath(array $service)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->dataPath."/".$service['name'];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |