diff --git a/resources/sql/autopatches/20180213.hoax.01.hoax.sql b/resources/sql/autopatches/20180213.hoax.01.hoax.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20180213.hoax.01.hoax.sql @@ -0,0 +1,8 @@ +CREATE TABLE {$NAMESPACE}_drydock.drydock_hoax ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + phid VARBINARY(64) NOT NULL, + name VARCHAR(128) NOT NULL COLLATE {$COLLATE_TEXT}, + state VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT}, + dateCreated INT UNSIGNED NOT NULL, + dateModified INT UNSIGNED NOT NULL +) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1048,6 +1048,11 @@ 'DrydockDefaultEditCapability' => 'applications/drydock/capability/DrydockDefaultEditCapability.php', 'DrydockDefaultViewCapability' => 'applications/drydock/capability/DrydockDefaultViewCapability.php', 'DrydockFilesystemInterface' => 'applications/drydock/interface/filesystem/DrydockFilesystemInterface.php', + 'DrydockHoax' => 'applications/drydock/storage/DrydockHoax.php', + 'DrydockHoaxBlueprintImplementation' => 'applications/drydock/blueprint/DrydockHoaxBlueprintImplementation.php', + 'DrydockHoaxCommandInterface' => 'applications/drydock/interface/command/DrydockHoaxCommandInterface.php', + 'DrydockHoaxLog' => 'applications/drydock/storage/DrydockHoaxLog.php', + 'DrydockHoaxPHIDType' => 'applications/drydock/phid/DrydockHoaxPHIDType.php', 'DrydockInterface' => 'applications/drydock/interface/DrydockInterface.php', 'DrydockLandRepositoryOperation' => 'applications/drydock/operation/DrydockLandRepositoryOperation.php', 'DrydockLease' => 'applications/drydock/storage/DrydockLease.php', @@ -1084,6 +1089,7 @@ 'DrydockLogSearchEngine' => 'applications/drydock/query/DrydockLogSearchEngine.php', 'DrydockLogType' => 'applications/drydock/logtype/DrydockLogType.php', 'DrydockManagementCommandWorkflow' => 'applications/drydock/management/DrydockManagementCommandWorkflow.php', + 'DrydockManagementHoaxWorkflow' => 'applications/drydock/management/DrydockManagementHoaxWorkflow.php', 'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php', 'DrydockManagementReclaimWorkflow' => 'applications/drydock/management/DrydockManagementReclaimWorkflow.php', 'DrydockManagementReleaseLeaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseLeaseWorkflow.php', @@ -6269,6 +6275,17 @@ 'DrydockDefaultEditCapability' => 'PhabricatorPolicyCapability', 'DrydockDefaultViewCapability' => 'PhabricatorPolicyCapability', 'DrydockFilesystemInterface' => 'DrydockInterface', + 'DrydockHoax' => array( + 'DrydockDAO', + 'PhabricatorPolicyInterface', + ), + 'DrydockHoaxBlueprintImplementation' => 'DrydockBlueprintImplementation', + 'DrydockHoaxCommandInterface' => 'DrydockCommandInterface', + 'DrydockHoaxLog' => array( + 'DrydockDAO', + 'PhabricatorPolicyInterface', + ), + 'DrydockHoaxPHIDType' => 'PhabricatorPHIDType', 'DrydockInterface' => 'Phobject', 'DrydockLandRepositoryOperation' => 'DrydockRepositoryOperationType', 'DrydockLease' => array( @@ -6311,6 +6328,7 @@ 'DrydockLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockLogType' => 'Phobject', 'DrydockManagementCommandWorkflow' => 'DrydockManagementWorkflow', + 'DrydockManagementHoaxWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementReclaimWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementReleaseLeaseWorkflow' => 'DrydockManagementWorkflow', diff --git a/src/applications/drydock/blueprint/DrydockHoaxBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockHoaxBlueprintImplementation.php new file mode 100644 --- /dev/null +++ b/src/applications/drydock/blueprint/DrydockHoaxBlueprintImplementation.php @@ -0,0 +1,184 @@ +shouldLimitAllocatingPoolSize($blueprint)) { + return false; + } + + return true; + } + + public function allocateResource( + DrydockBlueprint $blueprint, + DrydockLease $lease) { + + $name = Filesystem::readRandomCharacters(8); + + $hoax = id(new DrydockHoax()) + ->setName('hoax-'.$name.'.example.horse') + ->setState('running') + ->save(); + + $resource = $this->newResourceTemplate($blueprint) + ->setAttribute('hoaxPHID', $hoax->getPHID()) + ->setAttribute('hoaxName', $hoax->getName()); + + $lease_flavor = $lease->getAttribute('flavor'); + if ($lease_flavor !== null) { + $resource->setAttribute('flavor', $lease_flavor); + } + + $slot_lock = $this->getConcurrentResourceLimitSlotLock($blueprint); + if ($slot_lock !== null) { + $resource->needSlotLock($slot_lock); + } + + return $resource->allocateResource(); + } + + public function activateResource( + DrydockBlueprint $blueprint, + DrydockResource $resource) { + return $resource->activateResource($blueprint, $resource); + } + + public function activateLease( + DrydockBlueprint $blueprint, + DrydockResource $resource, + DrydockLease $lease) { + + return $lease->activateOnResource($resource); + } + + public function destroyResource( + DrydockBlueprint $blueprint, + DrydockResource $resource) { + + $hoax = id(new DrydockHoax())->loadOneWhere( + 'phid = %s', + $resource->getAttribute('hoaxPHID')); + + $hoax->setState('destroyed')->save(); + } + + public function getResourceName( + DrydockBlueprint $blueprint, + DrydockResource $resource) { + + $hoax_name = $resource->getAttribute('hoaxName', pht('')); + + return pht('Hoax (%s)', $hoax_name); + } + + public function canAcquireLeaseOnResource( + DrydockBlueprint $blueprint, + DrydockResource $resource, + DrydockLease $lease) { + + // If the lease has a flavor, the resource needs to have the same flavor. + $lease_flavor = $lease->getAttribute('flavor'); + if ($lease_flavor !== null) { + $resource_flavor = $resource->getAttribute('flavor'); + if ($resource_flavor !== $lease_flavor) { + return false; + } + } + + if (!DrydockSlotLock::isLockFree($this->getLeaseSlotLock($resource))) { + return false; + } + + return true; + } + + public function acquireLease( + DrydockBlueprint $blueprint, + DrydockResource $resource, + DrydockLease $lease) { + + $lease + ->needSlotLock($this->getLeaseSlotLock($resource)) + ->acquireOnResource($resource); + } + + public function didReleaseLease( + DrydockBlueprint $blueprint, + DrydockResource $resource, + DrydockLease $lease) { + return; + } + + public function destroyLease( + DrydockBlueprint $blueprint, + DrydockResource $resource, + DrydockLease $lease) { + return; + } + + public function getType() { + return 'host'; + } + + public function getInterface( + DrydockBlueprint $blueprint, + DrydockResource $resource, + DrydockLease $lease, + $type) { + + $viewer = PhabricatorUser::getOmnipotentUser(); + + switch ($type) { + case DrydockCommandInterface::INTERFACE_TYPE: + return new DrydockHoaxCommandInterface(); + } + } + + protected function getCustomFieldSpecifications() { + return array(); + } + + + private function getLeaseSlotLock(DrydockResource $resource) { + $resource_phid = $resource->getPHID(); + return "hoax.lease({$resource_phid})"; + } + +} diff --git a/src/applications/drydock/interface/command/DrydockHoaxCommandInterface.php b/src/applications/drydock/interface/command/DrydockHoaxCommandInterface.php new file mode 100644 --- /dev/null +++ b/src/applications/drydock/interface/command/DrydockHoaxCommandInterface.php @@ -0,0 +1,17 @@ +setName('hoax') + ->setSynopsis(pht('Pretend to run a command.')) + ->setArguments( + array( + array( + 'name' => 'command', + 'param' => 'commmand', + 'help' => pht('Command to run.'), + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $command = $args->getArg('command'); + + $argv = id(new PhutilShellLexer())->splitArguments($command); + + + switch ($argv[0]) { + case 'ls': + echo "README\n"; + return 0; + default: + echo tsprintf( + "%s\n", + pht( + 'Unknown command "%s"! Make sure this binary is properly '. + 'installed on your HoaxOS system.', + $argv[0])); + return 1; + } + } + +} diff --git a/src/applications/drydock/phid/DrydockHoaxPHIDType.php b/src/applications/drydock/phid/DrydockHoaxPHIDType.php new file mode 100644 --- /dev/null +++ b/src/applications/drydock/phid/DrydockHoaxPHIDType.php @@ -0,0 +1,48 @@ +withPHIDs($phids); + } + + public function loadHandles( + PhabricatorHandleQuery $query, + array $handles, + array $objects) { + + foreach ($handles as $phid => $handle) { + $hoax = $objects[$phid]; + $id = $hoax->getID(); + + $handle->setName( + pht( + 'Hoax %d: %s', + $id, + $hoax->getName())); + } + } + +} diff --git a/src/applications/drydock/storage/DrydockHoax.php b/src/applications/drydock/storage/DrydockHoax.php new file mode 100644 --- /dev/null +++ b/src/applications/drydock/storage/DrydockHoax.php @@ -0,0 +1,47 @@ + true, + self::CONFIG_COLUMN_SCHEMA => array( + 'name' => 'text128', + 'state' => 'text32', + ), + self::CONFIG_KEY_SCHEMA => array( + ), + ) + parent::getConfiguration(); + } + + public function getPHIDType() { + return DrydockHoaxPHIDType::TYPECONST; + } + +/* -( PhabricatorPolicyInterface )----------------------------------------- */ + + + public function getCapabilities() { + return array( + PhabricatorPolicyCapability::CAN_VIEW, + ); + } + + public function getPolicy($capability) { + return PhabricatorPolicies::getMostOpenPolicy(); + } + + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { + return false; + } + + public function describeAutomaticCapability($capability) { + return pht('All users can view hoaxes.'); + } + +} diff --git a/src/applications/drydock/storage/DrydockHoaxLog.php b/src/applications/drydock/storage/DrydockHoaxLog.php new file mode 100644 --- /dev/null +++ b/src/applications/drydock/storage/DrydockHoaxLog.php @@ -0,0 +1,41 @@ + array( + 'message' => 'text', + ), + self::CONFIG_KEY_SCHEMA => array( + ), + ) + parent::getConfiguration(); + } + +/* -( PhabricatorPolicyInterface )----------------------------------------- */ + + + public function getCapabilities() { + return array( + PhabricatorPolicyCapability::CAN_VIEW, + ); + } + + public function getPolicy($capability) { + return PhabricatorPolicies::getMostOpenPolicy(); + } + + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { + return false; + } + + public function describeAutomaticCapability($capability) { + return pht('All users can view hoax logs.'); + } + +}