mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 14:52:41 +01:00
Add skeleton code for Almanac Interfaces to have real transactions
Summary: Depends on D19322. Ref T13120. Ref T12414. Currently, `AlmanacDevice` has a bit of a beast of a `TYPE_INTERFACE` transaction that fully creates a complex Interface object. This isn't very flexible or consistent, and Interfaces are complex enough to reasonably have their own object behaviors (for example, they have their own PHIDs). The complexity of this transaction makes modularizing `AlmanacDevice` transactions tricky. To simplify this, move Interface toward having its own set of normal transactions. This change just adds some reasonable-looking transactions; it doesn't actually hook them up in the UI or make them reachable. I'll test that they actually work as I swap the UI over. We may also have some code using the `TYPE_INTERFACE` transaction in Phacility support stuff, so that may need to wait a week to actually phase out. Test Plan: Ran `bin/storage upgrade` and `arc liberate`. This code isn't reachable yet. Reviewers: amckinley Reviewed By: amckinley Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam Maniphest Tasks: T13120, T12414 Differential Revision: https://secure.phabricator.com/D19323
This commit is contained in:
parent
580409b562
commit
f9c6a69d9c
10 changed files with 316 additions and 1 deletions
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE {$NAMESPACE}_almanac.almanac_interfacetransaction (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
authorPHID VARBINARY(64) NOT NULL,
|
||||
objectPHID VARBINARY(64) NOT NULL,
|
||||
viewPolicy VARBINARY(64) NOT NULL,
|
||||
editPolicy VARBINARY(64) NOT NULL,
|
||||
commentPHID VARBINARY(64) DEFAULT NULL,
|
||||
commentVersion INT UNSIGNED NOT NULL,
|
||||
transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `key_phid` (`phid`),
|
||||
KEY `key_object` (`objectPHID`)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
|
@ -57,12 +57,19 @@ phutil_register_library_map(array(
|
|||
'AlmanacDrydockPoolServiceType' => 'applications/almanac/servicetype/AlmanacDrydockPoolServiceType.php',
|
||||
'AlmanacEditor' => 'applications/almanac/editor/AlmanacEditor.php',
|
||||
'AlmanacInterface' => 'applications/almanac/storage/AlmanacInterface.php',
|
||||
'AlmanacInterfaceAddressTransaction' => 'applications/almanac/xaction/AlmanacInterfaceAddressTransaction.php',
|
||||
'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php',
|
||||
'AlmanacInterfaceDeleteController' => 'applications/almanac/controller/AlmanacInterfaceDeleteController.php',
|
||||
'AlmanacInterfaceDeviceTransaction' => 'applications/almanac/xaction/AlmanacInterfaceDeviceTransaction.php',
|
||||
'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php',
|
||||
'AlmanacInterfaceEditor' => 'applications/almanac/editor/AlmanacInterfaceEditor.php',
|
||||
'AlmanacInterfaceNetworkTransaction' => 'applications/almanac/xaction/AlmanacInterfaceNetworkTransaction.php',
|
||||
'AlmanacInterfacePHIDType' => 'applications/almanac/phid/AlmanacInterfacePHIDType.php',
|
||||
'AlmanacInterfacePortTransaction' => 'applications/almanac/xaction/AlmanacInterfacePortTransaction.php',
|
||||
'AlmanacInterfaceQuery' => 'applications/almanac/query/AlmanacInterfaceQuery.php',
|
||||
'AlmanacInterfaceTableView' => 'applications/almanac/view/AlmanacInterfaceTableView.php',
|
||||
'AlmanacInterfaceTransaction' => 'applications/almanac/storage/AlmanacInterfaceTransaction.php',
|
||||
'AlmanacInterfaceTransactionType' => 'applications/almanac/xaction/AlmanacInterfaceTransactionType.php',
|
||||
'AlmanacKeys' => 'applications/almanac/util/AlmanacKeys.php',
|
||||
'AlmanacManageClusterServicesCapability' => 'applications/almanac/capability/AlmanacManageClusterServicesCapability.php',
|
||||
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
|
||||
|
@ -5243,13 +5250,21 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
),
|
||||
'AlmanacInterfaceAddressTransaction' => 'AlmanacNetworkTransactionType',
|
||||
'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'AlmanacInterfaceDeleteController' => 'AlmanacDeviceController',
|
||||
'AlmanacInterfaceDeviceTransaction' => 'AlmanacNetworkTransactionType',
|
||||
'AlmanacInterfaceEditController' => 'AlmanacDeviceController',
|
||||
'AlmanacInterfaceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'AlmanacInterfaceNetworkTransaction' => 'AlmanacNetworkTransactionType',
|
||||
'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType',
|
||||
'AlmanacInterfacePortTransaction' => 'AlmanacNetworkTransactionType',
|
||||
'AlmanacInterfaceQuery' => 'AlmanacQuery',
|
||||
'AlmanacInterfaceTableView' => 'AphrontView',
|
||||
'AlmanacInterfaceTransaction' => 'PhabricatorModularTransaction',
|
||||
'AlmanacInterfaceTransactionType' => 'AlmanacTransactionType',
|
||||
'AlmanacKeys' => 'Phobject',
|
||||
'AlmanacManageClusterServicesCapability' => 'PhabricatorPolicyCapability',
|
||||
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
|
||||
|
|
22
src/applications/almanac/editor/AlmanacInterfaceEditor.php
Normal file
22
src/applications/almanac/editor/AlmanacInterfaceEditor.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorAlmanacApplication';
|
||||
}
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Almanac Interface');
|
||||
}
|
||||
|
||||
public function getCreateObjectTitle($author, $object) {
|
||||
return pht('%s created this interface.', $author);
|
||||
}
|
||||
|
||||
public function getCreateObjectTitleForFeed($author, $object) {
|
||||
return pht('%s created %s.', $author, $object);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,8 @@ final class AlmanacInterface
|
|||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
PhabricatorExtendedPolicyInterface,
|
||||
PhabricatorApplicationTransactionInterface {
|
||||
|
||||
protected $devicePHID;
|
||||
protected $networkPHID;
|
||||
|
@ -154,4 +155,26 @@ final class AlmanacInterface
|
|||
$this->delete();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
|
||||
public function getApplicationTransactionEditor() {
|
||||
return new AlmanacInterfaceEditor();
|
||||
}
|
||||
|
||||
public function getApplicationTransactionObject() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionTemplate() {
|
||||
return new AlmanacInterfaceTransaction();
|
||||
}
|
||||
|
||||
public function willRenderTimeline(
|
||||
PhabricatorApplicationTransactionView $timeline,
|
||||
AphrontRequest $request) {
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceTransaction
|
||||
extends PhabricatorModularTransaction {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
return AlmanacInterfacePHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionCommentObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getBaseTransactionClass() {
|
||||
return 'AlmanacInterfaceTransactionType';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceAddressTransaction
|
||||
extends AlmanacNetworkTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'almanac:interface:address';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getAddress();
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setAddress($value);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s changed the address for this interface from %s to %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldValue(),
|
||||
$this->renderNewValue());
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
if ($this->isEmptyTextTransaction($object->getAddress(), $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('Interfaces must have an address.'));
|
||||
}
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
|
||||
// NOTE: For now, we don't validate addresses. We generally expect users
|
||||
// to provide IPv4 addresses, but it's reasonable for them to provide
|
||||
// IPv6 addresses, and some installs currently use DNS names. This is
|
||||
// off-label but works today.
|
||||
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceDeviceTransaction
|
||||
extends AlmanacNetworkTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'almanac:interface:device';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getDevicePHID();
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setDevicePHID($value);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s changed the device for this interface from %s to %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldHandle(),
|
||||
$this->renderNewHandle());
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
if ($this->isEmptyTextTransaction($object->getAddress(), $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('Interfaces must have a device.'));
|
||||
}
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
if (!$this->isNewObject()) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'The device for an interface can not be changed once it has '.
|
||||
'been created.'),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
|
||||
$device_phid = $xaction->getNewValue();
|
||||
$devices = id(new AlmanacDeviceQuery())
|
||||
->setViewer($this->getActor())
|
||||
->withPHIDs(array($device_phid))
|
||||
->execute();
|
||||
if (!$devices) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'You can not attach an interface to a nonexistent or restricted '.
|
||||
'device.'),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceNetworkTransaction
|
||||
extends AlmanacNetworkTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'almanac:interface:network';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getNetworkPHID();
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setNetworkPHID($value);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s changed the network for this interface from %s to %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldHandle(),
|
||||
$this->renderNewHandle());
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
$network_phid = $object->getNetworkPHID();
|
||||
if ($this->isEmptyTextTransaction($network_phid, $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('Interfaces must have a network.'));
|
||||
}
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$network_phid = $xaction->getNewValue();
|
||||
|
||||
$networks = id(new AlmanacNetworkQuery())
|
||||
->setViewer($this->getActor())
|
||||
->withPHIDs(array($network_phid))
|
||||
->execute();
|
||||
if (!$networks) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'You can not put an interface on a nonexistent or restricted '.
|
||||
'network.'),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfacePortTransaction
|
||||
extends AlmanacNetworkTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'almanac:interface:port';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
$port = $object->getPort();
|
||||
|
||||
if ($port !== null) {
|
||||
$port = (int)$port;
|
||||
}
|
||||
|
||||
return $port;
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setPort((int)$value);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s changed the port for this interface from %s to %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldValue(),
|
||||
$this->renderNewValue());
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('Interfaces must have a port number.'));
|
||||
}
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$port = $xaction->getNewValue();
|
||||
|
||||
$port = (int)$port;
|
||||
if ($port < 1 || $port > 65535) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht('Port numbers must be between 1 and 65535, inclusive.'),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacInterfaceTransactionType
|
||||
extends AlmanacTransactionType {}
|
Loading…
Reference in a new issue