public function executeAcquireLease(DrydockResource $resource, DrydockLease $lease)
    {
        $key = Filesystem::readRandomCharacters(12);
        $ports = $resource->getAttribute('ports', array());
        for ($ii = 2000;; $ii++) {
            if (empty($ports[$ii])) {
                $ports[$ii] = $lease->getID();
                $port = $ii;
                break;
            }
        }
        $resource->setAttribute('ports', $ports);
        $resource->save();
        $host = $resource->getAttribute('host');
        $lease->setAttribute('port', $port);
        $lease->setAttribute('key', $key);
        $lease->save();
        $config = <<<EOCONFIG

Listen *:{$port}
<VirtualHost *:{$port}>
  DocumentRoot  /opt/drydock/webroot/{$key}/
  ServerName {$host}
</VirtualHost>
EOCONFIG;
        $cmd = $this->getInterface($resource, $lease, 'command');
        $cmd->execx(<<<EOSETUP
sudo mkdir -p %s &&
sudo sh -c %s &&
sudo /etc/init.d/httpd restart
EOSETUP
, "/opt/drydock/webroot/{$key}/", csprintf('echo %s > %s', $config, "/etc/httpd/conf.d/drydock-{$key}.conf"));
        $lease->setAttribute('uri', "http://{$host}:{$port}/");
        $lease->save();
    }
 protected function executeAcquireLease(DrydockResource $resource, DrydockLease $lease)
 {
     // Because preallocated resources are manually created, we should verify
     // we have all the information we need.
     PhutilTypeSpec::checkMap($resource->getAttributesForTypeSpec(array('platform', 'host', 'port', 'credential', 'path')), array('platform' => 'string', 'host' => 'string', 'port' => 'string', 'credential' => 'string', 'path' => 'string'));
     $v_platform = $resource->getAttribute('platform');
     $v_path = $resource->getAttribute('path');
     // Similar to DrydockLocalHostBlueprint, we create a folder
     // on the remote host that the lease can use.
     $lease_id = $lease->getID();
     // Can't use DIRECTORY_SEPERATOR here because that is relevant to
     // the platform we're currently running on, not the platform we are
     // remoting to.
     $separator = '/';
     if ($v_platform === 'windows') {
         $separator = '\\';
     }
     // Clean up the directory path a little.
     $base_path = rtrim($v_path, '/');
     $base_path = rtrim($base_path, '\\');
     $full_path = $base_path . $separator . $lease_id;
     $cmd = $lease->getInterface('command');
     $cmd->execx('mkdir %s', $full_path);
     $lease->setAttribute('path', $full_path);
 }
 public function activateLease(DrydockBlueprint $blueprint, DrydockResource $resource, DrydockLease $lease)
 {
     $host_lease = $this->loadHostLease($resource);
     $command_type = DrydockCommandInterface::INTERFACE_TYPE;
     $interface = $host_lease->getInterface($command_type);
     $map = $lease->getAttribute('repositories.map');
     $root = $resource->getAttribute('workingcopy.root');
     $default = null;
     foreach ($map as $directory => $spec) {
         $cmd = array();
         $arg = array();
         $cmd[] = 'cd %s';
         $arg[] = "{$root}/repo/{$directory}/";
         $cmd[] = 'git clean -d --force';
         $cmd[] = 'git fetch';
         $commit = idx($spec, 'commit');
         $branch = idx($spec, 'branch');
         $ref = idx($spec, 'ref');
         if ($commit !== null) {
             $cmd[] = 'git reset --hard %s';
             $arg[] = $commit;
         } else {
             if ($branch !== null) {
                 $cmd[] = 'git checkout %s';
                 $arg[] = $branch;
                 $cmd[] = 'git reset --hard origin/%s';
                 $arg[] = $branch;
             } else {
                 if ($ref) {
                     $ref_uri = $ref['uri'];
                     $ref_ref = $ref['ref'];
                     $cmd[] = 'git fetch --no-tags -- %s +%s:%s';
                     $arg[] = $ref_uri;
                     $arg[] = $ref_ref;
                     $arg[] = $ref_ref;
                     $cmd[] = 'git checkout %s';
                     $arg[] = $ref_ref;
                     $cmd[] = 'git reset --hard %s';
                     $arg[] = $ref_ref;
                 } else {
                     $cmd[] = 'git reset --hard HEAD';
                 }
             }
         }
         $cmd = implode(' && ', $cmd);
         $argv = array_merge(array($cmd), $arg);
         $result = call_user_func_array(array($interface, 'execx'), $argv);
         if (idx($spec, 'default')) {
             $default = $directory;
         }
     }
     if ($default === null) {
         $default = head_key($map);
     }
     // TODO: Use working storage?
     $lease->setAttribute('workingcopy.default', "{$root}/repo/{$default}/");
     $lease->activateOnResource($resource);
 }
 private function applyMerge(DrydockLease $lease, DrydockCommandInterface $interface, array $merge)
 {
     $src_uri = $merge['src.uri'];
     $src_ref = $merge['src.ref'];
     $interface->execx('git fetch --no-tags -- %s +%s:%s', $src_uri, $src_ref, $src_ref);
     // NOTE: This can never actually generate a commit because we pass
     // "--squash", but git sometimes runs code to check that a username and
     // email are configured anyway.
     $real_command = csprintf('git -c user.name=%s -c user.email=%s merge --no-stat --squash -- %R', 'drydock', 'drydock@phabricator', $src_ref);
     // Show the user a simplified command if the operation fails and we need to
     // report an error.
     $show_command = csprintf('git merge --squash -- %R', $src_ref);
     try {
         $interface->execx('%C', $real_command);
     } catch (CommandException $ex) {
         $error = DrydockCommandError::newFromCommandException(self::PHASE_SQUASHMERGE, $show_command, $ex);
         $lease->setAttribute('workingcopy.vcs.error', $error);
         throw $ex;
     }
 }
 protected function setWorkingCopyVCSErrorFromCommandException(DrydockLease $lease, $phase, $command, CommandException $ex)
 {
     $error = array('phase' => $phase, 'command' => (string) $command, 'raw' => (string) $ex->getCommand(), 'err' => $ex->getError(), 'stdout' => $ex->getStdout(), 'stderr' => $ex->getStderr());
     $lease->setAttribute('workingcopy.vcs.error', $error);
 }
 private function applyMerge(DrydockLease $lease, DrydockCommandInterface $interface, array $merge)
 {
     $src_uri = $merge['src.uri'];
     $src_ref = $merge['src.ref'];
     try {
         $interface->execx('git fetch --no-tags -- %s +%s:%s', $src_uri, $src_ref, $src_ref);
     } catch (CommandException $ex) {
         $display_command = csprintf('git fetch %R +%R:%R', $src_uri, $src_ref, $src_ref);
         $error = DrydockCommandError::newFromCommandException($ex)->setPhase(self::PHASE_MERGEFETCH)->setDisplayCommand($display_command);
         $lease->setAttribute('workingcopy.vcs.error', $error->toDictionary());
         throw $ex;
     }
     // NOTE: This can never actually generate a commit because we pass
     // "--squash", but git sometimes runs code to check that a username and
     // email are configured anyway.
     $real_command = csprintf('git -c user.name=%s -c user.email=%s merge --no-stat --squash -- %R', 'drydock', 'drydock@phabricator', $src_ref);
     try {
         $interface->execx('%C', $real_command);
     } catch (CommandException $ex) {
         $display_command = csprintf('git merge --squash %R', $src_ref);
         $error = DrydockCommandError::newFromCommandException($ex)->setPhase(self::PHASE_SQUASHMERGE)->setDisplayCommand($display_command);
         $lease->setAttribute('workingcopy.vcs.error', $error->toDictionary());
         throw $ex;
     }
 }