mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-17 20:32:41 +01:00
Store Almanac "service types" instead of "service classes"
Summary: Ref T10449. Currently, we store classes (like "AlmanacClusterRepositoryServiceType") in the database. Instead, store types (like "cluster.repository"). This is a small change, but types are a little more flexible (they let us freely reanme classes), a little cleaner (fewer magic strings in the codebase), and a little better for API usage (they're more human readable). Make this minor usability change now, before we unprototype. Also make services searchable by type. Also remove old Almanac API endpoints. Test Plan: - Ran migration, verified all data migrated properly. - Created, edited, rebound, and changed properties of services. - Searched for services by service type. - Reviewed available Conduit methods. Reviewers: chad Reviewed By: chad Subscribers: yelirekim Maniphest Tasks: T10449 Differential Revision: https://secure.phabricator.com/D15346
This commit is contained in:
parent
4c97d88aa4
commit
7d4b323da2
23 changed files with 226 additions and 282 deletions
2
resources/sql/autopatches/20160225.almanac.2.stype.sql
Normal file
2
resources/sql/autopatches/20160225.almanac.2.stype.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_almanac.almanac_service
|
||||
CHANGE serviceClass serviceType VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT};
|
30
resources/sql/autopatches/20160225.almanac.3.stype.php
Normal file
30
resources/sql/autopatches/20160225.almanac.3.stype.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
// Previously, Almanac services stored a "serviceClass". Migrate these to
|
||||
// new "serviceType" values.
|
||||
|
||||
$table = new AlmanacService();
|
||||
$conn_w = $table->establishConnection('w');
|
||||
|
||||
foreach (new LiskMigrationIterator($table) as $service) {
|
||||
|
||||
$new_type = null;
|
||||
try {
|
||||
$old_type = $service->getServiceType();
|
||||
$object = newv($old_type, array());
|
||||
$new_type = $object->getServiceTypeConstant();
|
||||
} catch (Exception $ex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$new_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
queryfx(
|
||||
$conn_w,
|
||||
'UPDATE %T SET serviceType = %s WHERE id = %d',
|
||||
$table->getTableName(),
|
||||
$new_type,
|
||||
$service->getID());
|
||||
}
|
|
@ -25,7 +25,6 @@ phutil_register_library_map(array(
|
|||
'AlmanacClusterDatabaseServiceType' => 'applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php',
|
||||
'AlmanacClusterRepositoryServiceType' => 'applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php',
|
||||
'AlmanacClusterServiceType' => 'applications/almanac/servicetype/AlmanacClusterServiceType.php',
|
||||
'AlmanacConduitAPIMethod' => 'applications/almanac/conduit/AlmanacConduitAPIMethod.php',
|
||||
'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php',
|
||||
'AlmanacController' => 'applications/almanac/controller/AlmanacController.php',
|
||||
'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php',
|
||||
|
@ -101,8 +100,6 @@ phutil_register_library_map(array(
|
|||
'AlmanacPropertyInterface' => 'applications/almanac/property/AlmanacPropertyInterface.php',
|
||||
'AlmanacPropertyQuery' => 'applications/almanac/query/AlmanacPropertyQuery.php',
|
||||
'AlmanacQuery' => 'applications/almanac/query/AlmanacQuery.php',
|
||||
'AlmanacQueryDevicesConduitAPIMethod' => 'applications/almanac/conduit/AlmanacQueryDevicesConduitAPIMethod.php',
|
||||
'AlmanacQueryServicesConduitAPIMethod' => 'applications/almanac/conduit/AlmanacQueryServicesConduitAPIMethod.php',
|
||||
'AlmanacSchemaSpec' => 'applications/almanac/storage/AlmanacSchemaSpec.php',
|
||||
'AlmanacSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacSearchEngineAttachment.php',
|
||||
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
|
||||
|
@ -120,6 +117,7 @@ phutil_register_library_map(array(
|
|||
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
|
||||
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
|
||||
'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php',
|
||||
'AlmanacServiceTypeDatasource' => 'applications/almanac/typeahead/AlmanacServiceTypeDatasource.php',
|
||||
'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php',
|
||||
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
|
||||
'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php',
|
||||
|
@ -4012,7 +4010,6 @@ phutil_register_library_map(array(
|
|||
'AlmanacClusterDatabaseServiceType' => 'AlmanacClusterServiceType',
|
||||
'AlmanacClusterRepositoryServiceType' => 'AlmanacClusterServiceType',
|
||||
'AlmanacClusterServiceType' => 'AlmanacServiceType',
|
||||
'AlmanacConduitAPIMethod' => 'ConduitAPIMethod',
|
||||
'AlmanacConsoleController' => 'AlmanacController',
|
||||
'AlmanacController' => 'PhabricatorController',
|
||||
'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability',
|
||||
|
@ -4120,8 +4117,6 @@ phutil_register_library_map(array(
|
|||
'AlmanacPropertyEditEngine' => 'PhabricatorEditEngine',
|
||||
'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'AlmanacQueryDevicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
|
||||
'AlmanacQueryServicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
|
||||
'AlmanacSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'AlmanacSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
||||
'AlmanacService' => array(
|
||||
|
@ -4149,6 +4144,7 @@ phutil_register_library_map(array(
|
|||
'AlmanacServiceTransaction' => 'AlmanacTransaction',
|
||||
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'AlmanacServiceType' => 'Phobject',
|
||||
'AlmanacServiceTypeDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase',
|
||||
'AlmanacServiceViewController' => 'AlmanacServiceController',
|
||||
'AlmanacTransaction' => 'PhabricatorApplicationTransaction',
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacConduitAPIMethod extends ConduitAPIMethod {
|
||||
|
||||
final public function getApplication() {
|
||||
return PhabricatorApplication::getByClass(
|
||||
'PhabricatorAlmanacApplication');
|
||||
}
|
||||
|
||||
public function getMethodStatus() {
|
||||
return self::METHOD_STATUS_DEPRECATED;
|
||||
}
|
||||
|
||||
public function getMethodStatusDescription() {
|
||||
return pht(
|
||||
'Almanac is a prototype application and its APIs are '.
|
||||
'subject to change.');
|
||||
}
|
||||
|
||||
protected function getServiceDictionary(AlmanacService $service) {
|
||||
return array(
|
||||
'id' => (int)$service->getID(),
|
||||
'phid' => $service->getPHID(),
|
||||
'name' => $service->getName(),
|
||||
'uri' => PhabricatorEnv::getProductionURI($service->getURI()),
|
||||
'serviceClass' => $service->getServiceClass(),
|
||||
'properties' => $this->getPropertiesDictionary($service),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getBindingDictionary(AlmanacBinding $binding) {
|
||||
return array(
|
||||
'id' => (int)$binding->getID(),
|
||||
'phid' => $binding->getPHID(),
|
||||
'properties' => $this->getPropertiesDictionary($binding),
|
||||
'interface' => $this->getInterfaceDictionary($binding->getInterface()),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getPropertiesDictionary(AlmanacPropertyInterface $obj) {
|
||||
$properties = $obj->getAlmanacProperties();
|
||||
return (object)mpull($properties, 'getFieldValue', 'getFieldName');
|
||||
}
|
||||
|
||||
protected function getInterfaceDictionary(AlmanacInterface $interface) {
|
||||
return array(
|
||||
'id' => (int)$interface->getID(),
|
||||
'phid' => $interface->getPHID(),
|
||||
'address' => $interface->getAddress(),
|
||||
'port' => (int)$interface->getPort(),
|
||||
'device' => $this->getDeviceDictionary($interface->getDevice()),
|
||||
'network' => $this->getNetworkDictionary($interface->getNetwork()),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getDeviceDictionary(AlmanacDevice $device) {
|
||||
return array(
|
||||
'id' => (int)$device->getID(),
|
||||
'phid' => $device->getPHID(),
|
||||
'name' => $device->getName(),
|
||||
'properties' => $this->getPropertiesDictionary($device),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getNetworkDictionary(AlmanacNetwork $network) {
|
||||
return array(
|
||||
'id' => (int)$network->getID(),
|
||||
'phid' => $network->getPHID(),
|
||||
'name' => $network->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacQueryDevicesConduitAPIMethod
|
||||
extends AlmanacConduitAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
||||
return 'almanac.querydevices';
|
||||
}
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Query Almanac devices.');
|
||||
}
|
||||
|
||||
protected function defineParamTypes() {
|
||||
return array(
|
||||
'ids' => 'optional list<id>',
|
||||
'phids' => 'optional list<phid>',
|
||||
'names' => 'optional list<phid>',
|
||||
) + self::getPagerParamTypes();
|
||||
}
|
||||
|
||||
protected function defineReturnType() {
|
||||
return 'list<wild>';
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$query = id(new AlmanacDeviceQuery())
|
||||
->setViewer($viewer);
|
||||
|
||||
$ids = $request->getValue('ids');
|
||||
if ($ids !== null) {
|
||||
$query->withIDs($ids);
|
||||
}
|
||||
|
||||
$phids = $request->getValue('phids');
|
||||
if ($phids !== null) {
|
||||
$query->withPHIDs($phids);
|
||||
}
|
||||
|
||||
$names = $request->getValue('names');
|
||||
if ($names !== null) {
|
||||
$query->withNames($names);
|
||||
}
|
||||
|
||||
$pager = $this->newPager($request);
|
||||
|
||||
$devices = $query->executeWithCursorPager($pager);
|
||||
|
||||
$data = array();
|
||||
foreach ($devices as $device) {
|
||||
$data[] = $this->getDeviceDictionary($device);
|
||||
}
|
||||
|
||||
$results = array(
|
||||
'data' => $data,
|
||||
);
|
||||
|
||||
return $this->addPagerResults($results, $pager);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacQueryServicesConduitAPIMethod
|
||||
extends AlmanacConduitAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
||||
return 'almanac.queryservices';
|
||||
}
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Query Almanac services.');
|
||||
}
|
||||
|
||||
protected function defineParamTypes() {
|
||||
return array(
|
||||
'ids' => 'optional list<id>',
|
||||
'phids' => 'optional list<phid>',
|
||||
'names' => 'optional list<phid>',
|
||||
'devicePHIDs' => 'optional list<phid>',
|
||||
'serviceClasses' => 'optional list<string>',
|
||||
) + self::getPagerParamTypes();
|
||||
}
|
||||
|
||||
protected function defineReturnType() {
|
||||
return 'list<wild>';
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$query = id(new AlmanacServiceQuery())
|
||||
->setViewer($viewer)
|
||||
->needBindings(true);
|
||||
|
||||
$ids = $request->getValue('ids');
|
||||
if ($ids !== null) {
|
||||
$query->withIDs($ids);
|
||||
}
|
||||
|
||||
$phids = $request->getValue('phids');
|
||||
if ($phids !== null) {
|
||||
$query->withPHIDs($phids);
|
||||
}
|
||||
|
||||
$names = $request->getValue('names');
|
||||
if ($names !== null) {
|
||||
$query->withNames($names);
|
||||
}
|
||||
|
||||
$classes = $request->getValue('serviceClasses');
|
||||
if ($classes !== null) {
|
||||
$query->withServiceClasses($classes);
|
||||
}
|
||||
|
||||
$device_phids = $request->getValue('devicePHIDs');
|
||||
if ($device_phids !== null) {
|
||||
$query->withDevicePHIDs($device_phids);
|
||||
}
|
||||
|
||||
$pager = $this->newPager($request);
|
||||
|
||||
$services = $query->executeWithCursorPager($pager);
|
||||
|
||||
$data = array();
|
||||
foreach ($services as $service) {
|
||||
$phid = $service->getPHID();
|
||||
|
||||
$service_bindings = $service->getBindings();
|
||||
$service_bindings = array_values($service_bindings);
|
||||
foreach ($service_bindings as $key => $service_binding) {
|
||||
$service_bindings[$key] = $this->getBindingDictionary($service_binding);
|
||||
}
|
||||
|
||||
$data[] = $this->getServiceDictionary($service) + array(
|
||||
'bindings' => $service_bindings,
|
||||
);
|
||||
}
|
||||
|
||||
$results = array(
|
||||
'data' => $data,
|
||||
);
|
||||
|
||||
return $this->addPagerResults($results, $pager);
|
||||
}
|
||||
|
||||
}
|
|
@ -34,21 +34,19 @@ final class AlmanacServiceEditController
|
|||
$this->requireApplicationCapability(
|
||||
AlmanacCreateServicesCapability::CAPABILITY);
|
||||
|
||||
$service_class = $request->getStr('serviceClass');
|
||||
$service_types = AlmanacServiceType::getAllServiceTypes();
|
||||
if (empty($service_types[$service_class])) {
|
||||
return $this->buildServiceTypeResponse($service_types, $cancel_uri);
|
||||
$service_type = $request->getStr('serviceType');
|
||||
|
||||
try {
|
||||
$service = AlmanacService::initializeNewService($service_type);
|
||||
} catch (Exception $ex) {
|
||||
return $this->buildServiceTypeResponse($cancel_uri);
|
||||
}
|
||||
|
||||
$service_type = $service_types[$service_class];
|
||||
if ($service_type->isClusterServiceType()) {
|
||||
if ($service->isClusterService()) {
|
||||
$this->requireApplicationCapability(
|
||||
AlmanacManageClusterServicesCapability::CAPABILITY);
|
||||
}
|
||||
|
||||
$service = AlmanacService::initializeNewService();
|
||||
$service->setServiceClass($service_class);
|
||||
$service->attachServiceType($service_type);
|
||||
$is_new = true;
|
||||
|
||||
$title = pht('Create Service');
|
||||
|
@ -125,7 +123,7 @@ final class AlmanacServiceEditController
|
|||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->addHiddenInput('edit', true)
|
||||
->addHiddenInput('serviceClass', $service->getServiceClass())
|
||||
->addHiddenInput('serviceType', $service->getServiceType())
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('Name'))
|
||||
|
@ -177,7 +175,9 @@ final class AlmanacServiceEditController
|
|||
));
|
||||
}
|
||||
|
||||
private function buildServiceTypeResponse(array $service_types, $cancel_uri) {
|
||||
private function buildServiceTypeResponse($cancel_uri) {
|
||||
$service_types = AlmanacServiceType::getAllServiceTypes();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
|
@ -197,7 +197,7 @@ final class AlmanacServiceEditController
|
|||
|
||||
$type_control = id(new AphrontFormRadioButtonControl())
|
||||
->setLabel(pht('Service Type'))
|
||||
->setName('serviceClass')
|
||||
->setName('serviceType')
|
||||
->setError($e_service);
|
||||
|
||||
foreach ($service_types as $service_type) {
|
||||
|
@ -211,7 +211,7 @@ final class AlmanacServiceEditController
|
|||
}
|
||||
|
||||
$type_control->addButton(
|
||||
get_class($service_type),
|
||||
$service_type->getServiceTypeConstant(),
|
||||
$service_type->getServiceTypeName(),
|
||||
array(
|
||||
$service_type->getServiceTypeDescription(),
|
||||
|
|
|
@ -76,7 +76,7 @@ final class AlmanacServiceViewController
|
|||
|
||||
$properties->addProperty(
|
||||
pht('Service Type'),
|
||||
$service->getServiceType()->getServiceTypeShortName());
|
||||
$service->getServiceImplementation()->getServiceTypeShortName());
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ final class AlmanacServiceQuery
|
|||
private $ids;
|
||||
private $phids;
|
||||
private $names;
|
||||
private $serviceClasses;
|
||||
private $serviceTypes;
|
||||
private $devicePHIDs;
|
||||
private $namePrefix;
|
||||
private $nameSuffix;
|
||||
|
@ -28,8 +28,8 @@ final class AlmanacServiceQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withServiceClasses(array $classes) {
|
||||
$this->serviceClasses = $classes;
|
||||
public function withServiceTypes(array $types) {
|
||||
$this->serviceTypes = $types;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -109,11 +109,11 @@ final class AlmanacServiceQuery
|
|||
$hashes);
|
||||
}
|
||||
|
||||
if ($this->serviceClasses !== null) {
|
||||
if ($this->serviceTypes !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'service.serviceClass IN (%Ls)',
|
||||
$this->serviceClasses);
|
||||
'service.serviceType IN (%Ls)',
|
||||
$this->serviceTypes);
|
||||
}
|
||||
|
||||
if ($this->devicePHIDs !== null) {
|
||||
|
@ -141,17 +141,19 @@ final class AlmanacServiceQuery
|
|||
}
|
||||
|
||||
protected function willFilterPage(array $services) {
|
||||
$service_types = AlmanacServiceType::getAllServiceTypes();
|
||||
$service_map = AlmanacServiceType::getAllServiceTypes();
|
||||
|
||||
foreach ($services as $key => $service) {
|
||||
$service_class = $service->getServiceClass();
|
||||
$service_type = idx($service_types, $service_class);
|
||||
if (!$service_type) {
|
||||
$implementation = idx($service_map, $service->getServiceType());
|
||||
|
||||
if (!$implementation) {
|
||||
$this->didRejectResult($service);
|
||||
unset($services[$key]);
|
||||
continue;
|
||||
}
|
||||
$service->attachServiceType($service_type);
|
||||
|
||||
$implementation = clone $implementation;
|
||||
$service->attachServiceImplementation($implementation);
|
||||
}
|
||||
|
||||
return $services;
|
||||
|
|
|
@ -16,7 +16,7 @@ final class AlmanacServiceSearchEngine
|
|||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return AlmanacService::initializeNewService();
|
||||
return new AlmanacService();
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
|
@ -34,6 +34,10 @@ final class AlmanacServiceSearchEngine
|
|||
$query->withDevicePHIDs($map['devicePHIDs']);
|
||||
}
|
||||
|
||||
if ($map['serviceTypes']) {
|
||||
$query->withServiceTypes($map['serviceTypes']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
@ -48,6 +52,11 @@ final class AlmanacServiceSearchEngine
|
|||
->setLabel(pht('Exact Names'))
|
||||
->setKey('names')
|
||||
->setDescription(pht('Search for services with specific names.')),
|
||||
id(new PhabricatorSearchDatasourceField())
|
||||
->setLabel(pht('Service Types'))
|
||||
->setKey('serviceTypes')
|
||||
->setDescription(pht('Find services by type.'))
|
||||
->setDatasource(id(new AlmanacServiceTypeDatasource())),
|
||||
id(new PhabricatorPHIDsSearchField())
|
||||
->setLabel(pht('Devices'))
|
||||
->setKey('devicePHIDs')
|
||||
|
@ -98,8 +107,8 @@ final class AlmanacServiceSearchEngine
|
|||
->setHref($service->getURI())
|
||||
->setObject($service)
|
||||
->addIcon(
|
||||
$service->getServiceType()->getServiceTypeIcon(),
|
||||
$service->getServiceType()->getServiceTypeShortName());
|
||||
$service->getServiceImplementation()->getServiceTypeIcon(),
|
||||
$service->getServiceImplementation()->getServiceTypeShortName());
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
final class AlmanacClusterDatabaseServiceType
|
||||
extends AlmanacClusterServiceType {
|
||||
|
||||
const SERVICETYPE = 'cluster.database';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Cluster Database');
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
final class AlmanacClusterRepositoryServiceType
|
||||
extends AlmanacClusterServiceType {
|
||||
|
||||
const SERVICETYPE = 'cluster.repository';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Cluster Repository');
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
final class AlmanacCustomServiceType extends AlmanacServiceType {
|
||||
|
||||
const SERVICETYPE = 'almanac.custom';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Custom');
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
final class AlmanacDrydockPoolServiceType extends AlmanacServiceType {
|
||||
|
||||
const SERVICETYPE = 'drydock.pool';
|
||||
|
||||
public function getServiceTypeShortName() {
|
||||
return pht('Drydock Pool');
|
||||
}
|
||||
|
|
|
@ -30,6 +30,11 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
abstract public function getServiceTypeDescription();
|
||||
|
||||
|
||||
final public function getServiceTypeConstant() {
|
||||
return $this->getPhobjectClassConstant('SERVICETYPE', 64);
|
||||
}
|
||||
|
||||
|
||||
public function getServiceTypeIcon() {
|
||||
return 'fa-cog';
|
||||
}
|
||||
|
@ -38,7 +43,7 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
* Return `true` if this service type is a Phabricator cluster service type.
|
||||
*
|
||||
* These special services change the behavior of Phabricator, and require
|
||||
* elevated permission to create.
|
||||
* elevated permission to create and edit.
|
||||
*
|
||||
* @return bool True if this is a Phabricator cluster service type.
|
||||
*/
|
||||
|
@ -63,6 +68,7 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
public static function getAllServiceTypes() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getServiceTypeConstant')
|
||||
->setSortMethod('getServiceTypeName')
|
||||
->execute();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,46 @@ final class AlmanacProperty
|
|||
return $this;
|
||||
}
|
||||
|
||||
public static function newPropertyUpdateTransactions(
|
||||
AlmanacPropertyInterface $object,
|
||||
array $properties,
|
||||
$only_builtins = false) {
|
||||
|
||||
$template = $object->getApplicationTransactionTemplate();
|
||||
$builtins = $object->getAlmanacPropertyFieldSpecifications();
|
||||
|
||||
$xactions = array();
|
||||
foreach ($properties as $name => $property) {
|
||||
if ($only_builtins && empty($builtins[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$xactions[] = id(clone $template)
|
||||
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_UPDATE)
|
||||
->setMetadataValue('almanac.property', $name)
|
||||
->setNewValue($property);
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
public static function newPropertyRemoveTransactions(
|
||||
AlmanacPropertyInterface $object,
|
||||
array $properties) {
|
||||
|
||||
$template = $object->getApplicationTransactionTemplate();
|
||||
|
||||
$xactions = array();
|
||||
foreach ($properties as $property) {
|
||||
$xactions[] = id(clone $template)
|
||||
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_REMOVE)
|
||||
->setMetadataValue('almanac.property', $property)
|
||||
->setNewValue(null);
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$hash = PhabricatorHash::digestForIndex($this->getFieldName());
|
||||
$this->setFieldIndex($hash);
|
||||
|
|
|
@ -17,17 +17,29 @@ final class AlmanacService
|
|||
protected $mailKey;
|
||||
protected $viewPolicy;
|
||||
protected $editPolicy;
|
||||
protected $serviceClass;
|
||||
protected $serviceType;
|
||||
|
||||
private $almanacProperties = self::ATTACHABLE;
|
||||
private $bindings = self::ATTACHABLE;
|
||||
private $serviceType = self::ATTACHABLE;
|
||||
private $serviceImplementation = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewService($type) {
|
||||
$type_map = AlmanacServiceType::getAllServiceTypes();
|
||||
|
||||
$implementation = idx($type_map, $type);
|
||||
if (!$implementation) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'No Almanac service type "%s" exists!',
|
||||
$type));
|
||||
}
|
||||
|
||||
public static function initializeNewService() {
|
||||
return id(new AlmanacService())
|
||||
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
|
||||
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
|
||||
->attachAlmanacProperties(array());
|
||||
->attachAlmanacProperties(array())
|
||||
->setServiceType($type)
|
||||
->attachServiceImplementation($implementation);
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
|
@ -37,7 +49,7 @@ final class AlmanacService
|
|||
'name' => 'text128',
|
||||
'nameIndex' => 'bytes12',
|
||||
'mailKey' => 'bytes20',
|
||||
'serviceClass' => 'text64',
|
||||
'serviceType' => 'text64',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_name' => array(
|
||||
|
@ -47,8 +59,8 @@ final class AlmanacService
|
|||
'key_nametext' => array(
|
||||
'columns' => array('name'),
|
||||
),
|
||||
'key_class' => array(
|
||||
'columns' => array('serviceClass'),
|
||||
'key_servicetype' => array(
|
||||
'columns' => array('serviceType'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
|
@ -78,22 +90,35 @@ final class AlmanacService
|
|||
return $this->assertAttached($this->bindings);
|
||||
}
|
||||
|
||||
public function getActiveBindings() {
|
||||
$bindings = $this->getBindings();
|
||||
|
||||
// Filter out disabled bindings.
|
||||
foreach ($bindings as $key => $binding) {
|
||||
if ($binding->getIsDisabled()) {
|
||||
unset($bindings[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $bindings;
|
||||
}
|
||||
|
||||
public function attachBindings(array $bindings) {
|
||||
$this->bindings = $bindings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getServiceType() {
|
||||
return $this->assertAttached($this->serviceType);
|
||||
public function getServiceImplementation() {
|
||||
return $this->assertAttached($this->serviceImplementation);
|
||||
}
|
||||
|
||||
public function attachServiceType(AlmanacServiceType $type) {
|
||||
$this->serviceType = $type;
|
||||
public function attachServiceImplementation(AlmanacServiceType $type) {
|
||||
$this->serviceImplementation = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isClusterService() {
|
||||
return $this->getServiceType()->isClusterServiceType();
|
||||
return $this->getServiceImplementation()->isClusterServiceType();
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,7 +153,7 @@ final class AlmanacService
|
|||
}
|
||||
|
||||
public function getAlmanacPropertyFieldSpecifications() {
|
||||
return $this->getServiceType()->getFieldSpecifications();
|
||||
return $this->getServiceImplementation()->getFieldSpecifications();
|
||||
}
|
||||
|
||||
public function newAlmanacPropertyEditEngine() {
|
||||
|
@ -246,12 +271,17 @@ final class AlmanacService
|
|||
->setKey('name')
|
||||
->setType('string')
|
||||
->setDescription(pht('The name of the service.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('serviceType')
|
||||
->setType('string')
|
||||
->setDescription(pht('The service type constant.')),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFieldValuesForConduit() {
|
||||
return array(
|
||||
'name' => $this->getName(),
|
||||
'serviceType' => $this->getServiceType(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ final class AlmanacServiceDatasource
|
|||
// selected, or show all services but mark the invalid ones disabled and
|
||||
// prevent their selection.
|
||||
|
||||
$service_classes = $this->getParameter('serviceClasses');
|
||||
if ($service_classes) {
|
||||
$services->withServiceClasses($service_classes);
|
||||
$service_types = $this->getParameter('serviceTypes');
|
||||
if ($service_types) {
|
||||
$services->withServiceTypes($service_types);
|
||||
}
|
||||
|
||||
$services = $this->executeQuery($services);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacServiceTypeDatasource
|
||||
extends PhabricatorTypeaheadDatasource {
|
||||
|
||||
public function getBrowseTitle() {
|
||||
return pht('Browse Service Types');
|
||||
}
|
||||
|
||||
public function getPlaceholderText() {
|
||||
return pht('Type a service type name...');
|
||||
}
|
||||
|
||||
public function getDatasourceApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
public function loadResults() {
|
||||
$results = $this->buildResults();
|
||||
return $this->filterResultsAgainstTokens($results);
|
||||
}
|
||||
|
||||
protected function renderSpecialTokens(array $values) {
|
||||
return $this->renderTokensFromResults($this->buildResults(), $values);
|
||||
}
|
||||
|
||||
private function buildResults() {
|
||||
$results = array();
|
||||
|
||||
$types = AlmanacServiceType::getAllServiceTypes();
|
||||
|
||||
$results = array();
|
||||
foreach ($types as $key => $type) {
|
||||
$results[$key] = id(new PhabricatorTypeaheadResult())
|
||||
->setName($type->getServiceTypeName())
|
||||
->setIcon($type->getServiceTypeIcon())
|
||||
->setPHID($key);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
|
@ -10,9 +10,9 @@ final class PhabricatorRepositoriesSetupCheck extends PhabricatorSetupCheck {
|
|||
|
||||
$cluster_services = id(new AlmanacServiceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withServiceClasses(
|
||||
->withServiceTypes(
|
||||
array(
|
||||
'AlmanacClusterRepositoryServiceType',
|
||||
AlmanacClusterRepositoryServiceType::SERVICETYPE,
|
||||
))
|
||||
->setLimit(1)
|
||||
->execute();
|
||||
|
|
|
@ -47,9 +47,9 @@ final class DiffusionRepositoryCreateController
|
|||
// allocations, we fail.
|
||||
$services = id(new AlmanacServiceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withServiceClasses(
|
||||
->withServiceTypes(
|
||||
array(
|
||||
'AlmanacClusterRepositoryServiceType',
|
||||
AlmanacClusterRepositoryServiceType::SERVICETYPE,
|
||||
))
|
||||
->needProperties(true)
|
||||
->execute();
|
||||
|
|
|
@ -184,7 +184,7 @@ final class DrydockAlmanacServiceHostBlueprintImplementation
|
|||
'type' => 'datasource',
|
||||
'datasource.class' => 'AlmanacServiceDatasource',
|
||||
'datasource.parameters' => array(
|
||||
'serviceClasses' => $this->getAlmanacServiceClasses(),
|
||||
'serviceTypes' => $this->getAlmanacServiceTypes(),
|
||||
),
|
||||
'required' => true,
|
||||
),
|
||||
|
@ -213,7 +213,7 @@ final class DrydockAlmanacServiceHostBlueprintImplementation
|
|||
$services = id(new AlmanacServiceQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($service_phids)
|
||||
->withServiceClasses($this->getAlmanacServiceClasses())
|
||||
->withServiceTypes($this->getAlmanacServiceTypes())
|
||||
->needBindings(true)
|
||||
->execute();
|
||||
$services = mpull($services, null, 'getPHID');
|
||||
|
@ -283,9 +283,9 @@ final class DrydockAlmanacServiceHostBlueprintImplementation
|
|||
return $this->freeBindings;
|
||||
}
|
||||
|
||||
private function getAlmanacServiceClasses() {
|
||||
private function getAlmanacServiceTypes() {
|
||||
return array(
|
||||
'AlmanacDrydockPoolServiceType',
|
||||
AlmanacDrydockPoolServiceType::SERVICETYPE,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2047,7 +2047,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
|||
'be loaded.'));
|
||||
}
|
||||
|
||||
$service_type = $service->getServiceType();
|
||||
$service_type = $service->getServiceImplementation();
|
||||
if (!($service_type instanceof AlmanacClusterRepositoryServiceType)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
|
|
Loading…
Reference in a new issue