The list of futures that the PHP agent maintains is never emptied after futures resolve. On subsequent passes through the loop in execute, all past futures are executed repeatedly.
Details
- Reviewers
epriestley - Group Reviewers
Blessed Reviewers - Commits
- rPHU73e2a1984abf: Discard futures after they resolve in phage
This didn't work previously.
<?php final class CIAWSDrydockHostCommandWorkflow extends CIAWSManagementWorkflow { protected function didConstruct() { $this ->setName('drydock-command') ->setSynopsis(pht('Interact with a drydock host.')) ->setArguments([ [ 'name' => 'lease', 'param' => 'id', 'help' => pht('ID of drydock lease to command.'), ], ]); } public function execute(PhutilArgumentParser $args) { $resource_id = $this->requireArgument($args, 'lease'); $viewer = PhabricatorUser::getOmnipotentUser(); $lease = (new DrydockLeaseQuery()) ->setViewer($viewer) ->withIDs([$resource_id]) ->executeOne(); $boot = new PhagePHPAgentBootloader(); $ssh = $lease->getInterface(DrydockCommandInterface::INTERFACE_TYPE); $exec = $ssh->getExecFuture('%C', $boot->getBootCommand()); $exec->write($boot->getBootSequence(), $keep_open = true); $exec_channel = new PhutilExecChannel($exec); $agent = new PhutilJSONProtocolChannel($exec_channel); $console = PhutilConsole::getConsole(); $cmd = null; $key = 1; while ($cmd !== 'exit') { $console->writeOut('**>** '); $cmd = fgets(STDIN); $cmd = rtrim($cmd, "\r\n"); $agent->write([ 'type' => 'EXEC', 'key' => $key++, 'command' => $cmd, ]); $message = $agent->waitForMessage(); $console->writeOut('%s', $message['stdout']); $console->writeErr('%s', $message['stderr']); } $agent->write(['type' => 'EXIT']); return 0; } }
Diff Detail
- Repository
- rPHU libphutil
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
This code is very proof-of-concept right now so I wouldn't be surprised if there's more stuff like this.
This use case is (using Phage as a fancier remote shell) is an interesting one. I didn't really think about having something like Drydock drive Phage clients, but I think it's legitimate / reasonable / non-abusive.
In the original Hypershell, the clients had a fair amount of logic in them, but I've tried to simplify them in Phage ("Hypershell 2"), so I expect the clients will remain as dumb as possible even when the command-and-control stuff for large tiers eventually gets built out. This should leave them well-aligned with use as a more flexible shell program that you don't need to deploy or configure.
I would expect to clean up the API at some point to support this use case, though.