mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
Move Drydock logs to PHIDs and increased structure
Summary: Ref T9252. Several general changes here: - Moves logs to use PHIDs instead of IDs. This generally improves flexibility (for example, it's a lot easier to render handles). - Adds `blueprintPHID` to logs. Although you can usually figure this out from the leasePHID or resourcePHID, it lets us query relevant logs on Blueprint views. - Instead of making logs a top-level object, make them strictly a sub-object of Blueprints, Resources and Leases. So you go Drydock > Lease > Logs, etc., to get to logs. - I might restore the "everything" view eventually, but it doesn't interact well with policies and I'm not sure it's very useful. A policy-violating `bin/drydock log` might be cleaner. - Policy-wise, we always show you that logs exist, we just don't show you log content if it's about something you can't see. This is similar to seeing restricted handles in other applications. - Instead of just having a message, give logs "type" + "data". This will let logs be more structured and translatable. This is similar to recent changes to Herald which seem to have worked well. Test Plan: Added some placeholder log writes, viewed those logs in the UI. {F855199} Reviewers: chad Reviewed By: chad Maniphest Tasks: T9252 Differential Revision: https://secure.phabricator.com/D14196
This commit is contained in:
parent
98006f2cf3
commit
2ef5b5321d
14 changed files with 488 additions and 252 deletions
25
resources/sql/autopatches/20150930.drydock.log.1.sql
Normal file
25
resources/sql/autopatches/20150930.drydock.log.1.sql
Normal file
|
@ -0,0 +1,25 @@
|
|||
TRUNCATE {$NAMESPACE}_drydock.drydock_log;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
DROP resourceID;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
DROP leaseID;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
DROP message;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
ADD blueprintPHID VARBINARY(64);
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
ADD resourcePHID VARBINARY(64);
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
ADD leasePHID VARBINARY(64);
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
ADD type VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT};
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_drydock.drydock_log
|
||||
ADD data LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT};
|
|
@ -47,7 +47,7 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication {
|
|||
return array(
|
||||
'/drydock/' => array(
|
||||
'' => 'DrydockConsoleController',
|
||||
'blueprint/' => array(
|
||||
'(?P<type>blueprint)/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DrydockBlueprintListController',
|
||||
'(?P<id>[1-9]\d*)/' => array(
|
||||
'' => 'DrydockBlueprintViewController',
|
||||
|
@ -55,29 +55,32 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication {
|
|||
'DrydockBlueprintDisableController',
|
||||
'resources/(?:query/(?P<queryKey>[^/]+)/)?' =>
|
||||
'DrydockResourceListController',
|
||||
'logs/(?:query/(?P<queryKey>[^/]+)/)?' =>
|
||||
'DrydockLogListController',
|
||||
),
|
||||
'create/' => 'DrydockBlueprintCreateController',
|
||||
'edit/(?:(?P<id>[1-9]\d*)/)?' => 'DrydockBlueprintEditController',
|
||||
),
|
||||
'resource/' => array(
|
||||
'(?P<type>resource)/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DrydockResourceListController',
|
||||
'(?P<id>[1-9]\d*)/' => array(
|
||||
'' => 'DrydockResourceViewController',
|
||||
'release/' => 'DrydockResourceReleaseController',
|
||||
'leases/(?:query/(?P<queryKey>[^/]+)/)?' =>
|
||||
'DrydockLeaseListController',
|
||||
'logs/(?:query/(?P<queryKey>[^/]+)/)?' =>
|
||||
'DrydockLogListController',
|
||||
),
|
||||
),
|
||||
'lease/' => array(
|
||||
'(?P<type>lease)/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DrydockLeaseListController',
|
||||
'(?P<id>[1-9]\d*)/' => array(
|
||||
'' => 'DrydockLeaseViewController',
|
||||
'release/' => 'DrydockLeaseReleaseController',
|
||||
'logs/(?:query/(?P<queryKey>[^/]+)/)?' =>
|
||||
'DrydockLogListController',
|
||||
),
|
||||
),
|
||||
'log/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DrydockLogListController',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -250,46 +250,6 @@ abstract class DrydockBlueprintImplementation extends Phobject {
|
|||
/* -( Logging )------------------------------------------------------------ */
|
||||
|
||||
|
||||
/**
|
||||
* @task log
|
||||
*/
|
||||
protected function logException(Exception $ex) {
|
||||
$this->log($ex->getMessage());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task log
|
||||
*/
|
||||
protected function log($message) {
|
||||
self::writeLog(null, null, $message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task log
|
||||
*/
|
||||
public static function writeLog(
|
||||
DrydockResource $resource = null,
|
||||
DrydockLease $lease = null,
|
||||
$message = null) {
|
||||
|
||||
$log = id(new DrydockLog())
|
||||
->setEpoch(time())
|
||||
->setMessage($message);
|
||||
|
||||
if ($resource) {
|
||||
$log->setResourceID($resource->getID());
|
||||
}
|
||||
|
||||
if ($lease) {
|
||||
$log->setLeaseID($lease->getID());
|
||||
}
|
||||
|
||||
$log->save();
|
||||
}
|
||||
|
||||
|
||||
public static function getAllBlueprintImplementations() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
|
|
|
@ -56,11 +56,19 @@ final class DrydockBlueprintViewController extends DrydockBlueprintController {
|
|||
new DrydockBlueprintTransactionQuery());
|
||||
$timeline->setShouldTerminate(true);
|
||||
|
||||
$log_query = id(new DrydockLogQuery())
|
||||
->withBlueprintPHIDs(array($blueprint->getPHID()));
|
||||
|
||||
$log_box = $this->buildLogBox(
|
||||
$log_query,
|
||||
$this->getApplicationURI("blueprint/{$id}/logs/query/all/"));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
$object_box,
|
||||
$resource_box,
|
||||
$log_box,
|
||||
$timeline,
|
||||
),
|
||||
array(
|
||||
|
|
|
@ -85,4 +85,31 @@ abstract class DrydockController extends PhabricatorController {
|
|||
->addRawContent($table);
|
||||
}
|
||||
|
||||
protected function buildLogBox(DrydockLogQuery $query, $all_uri) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$logs = $query
|
||||
->setViewer($viewer)
|
||||
->setLimit(100)
|
||||
->execute();
|
||||
|
||||
$log_table = id(new DrydockLogListView())
|
||||
->setUser($viewer)
|
||||
->setLogs($logs)
|
||||
->render();
|
||||
|
||||
$log_header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Logs'))
|
||||
->addActionLink(
|
||||
id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setHref($all_uri)
|
||||
->setIconFont('fa-search')
|
||||
->setText(pht('View All Logs')));
|
||||
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeader($log_header)
|
||||
->setTable($log_table);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$lease_uri = $this->getApplicationURI('lease/'.$lease->getID().'/');
|
||||
$id = $lease->getID();
|
||||
$lease_uri = $this->getApplicationURI("lease/{$id}/");
|
||||
|
||||
$title = pht('Lease %d', $lease->getID());
|
||||
|
||||
|
@ -29,20 +30,12 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
|
|||
$actions = $this->buildActionListView($lease);
|
||||
$properties = $this->buildPropertyListView($lease, $actions);
|
||||
|
||||
$pager = new PHUIPagerView();
|
||||
$pager->setURI(new PhutilURI($lease_uri), 'offset');
|
||||
$pager->setOffset($request->getInt('offset'));
|
||||
$log_query = id(new DrydockLogQuery())
|
||||
->withLeasePHIDs(array($lease->getPHID()));
|
||||
|
||||
$logs = id(new DrydockLogQuery())
|
||||
->setViewer($viewer)
|
||||
->withLeaseIDs(array($lease->getID()))
|
||||
->executeWithOffsetPager($pager);
|
||||
|
||||
$log_table = id(new DrydockLogListView())
|
||||
->setUser($viewer)
|
||||
->setLogs($logs)
|
||||
->render();
|
||||
$log_table->appendChild($pager);
|
||||
$log_box = $this->buildLogBox(
|
||||
$log_query,
|
||||
$this->getApplicationURI("lease/{$id}/logs/query/all/"));
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb($title, $lease_uri);
|
||||
|
@ -56,10 +49,6 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
|
|||
->addPropertyList($locks, pht('Slot Locks'))
|
||||
->addPropertyList($commands, pht('Commands'));
|
||||
|
||||
$log_box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Lease Logs'))
|
||||
->setTable($log_table);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
|
|
|
@ -3,13 +3,60 @@
|
|||
abstract class DrydockLogController
|
||||
extends DrydockController {
|
||||
|
||||
private $blueprint;
|
||||
private $resource;
|
||||
private $lease;
|
||||
|
||||
public function setBlueprint(DrydockBlueprint $blueprint) {
|
||||
$this->blueprint = $blueprint;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBlueprint() {
|
||||
return $this->blueprint;
|
||||
}
|
||||
|
||||
public function setResource(DrydockResource $resource) {
|
||||
$this->resource = $resource;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getResource() {
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
public function setLease(DrydockLease $lease) {
|
||||
$this->lease = $lease;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLease() {
|
||||
return $this->lease;
|
||||
}
|
||||
|
||||
public function buildSideNavView() {
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
||||
id(new DrydockLogSearchEngine())
|
||||
->setViewer($this->getRequest()->getUser())
|
||||
->addNavigationItems($nav->getMenu());
|
||||
$engine = id(new DrydockLogSearchEngine())
|
||||
->setViewer($this->getRequest()->getUser());
|
||||
|
||||
$blueprint = $this->getBlueprint();
|
||||
if ($blueprint) {
|
||||
$engine->setBlueprint($blueprint);
|
||||
}
|
||||
|
||||
$resource = $this->getResource();
|
||||
if ($resource) {
|
||||
$engine->setResource($resource);
|
||||
}
|
||||
|
||||
$lease = $this->getLease();
|
||||
if ($lease) {
|
||||
$engine->setLease($lease);
|
||||
}
|
||||
|
||||
$engine->addNavigationItems($nav->getMenu());
|
||||
|
||||
$nav->selectFilter(null);
|
||||
|
||||
|
@ -18,9 +65,54 @@ abstract class DrydockLogController
|
|||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Logs'),
|
||||
$this->getApplicationURI('log/'));
|
||||
|
||||
$blueprint = $this->getBlueprint();
|
||||
$resource = $this->getResource();
|
||||
$lease = $this->getLease();
|
||||
if ($blueprint) {
|
||||
$id = $blueprint->getID();
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Blueprints'),
|
||||
$this->getApplicationURI('blueprint/'));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
$blueprint->getBlueprintName(),
|
||||
$this->getApplicationURI("blueprint/{$id}/"));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Logs'),
|
||||
$this->getApplicationURI("blueprint/{$id}/logs/"));
|
||||
} else if ($resource) {
|
||||
$id = $resource->getID();
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Resources'),
|
||||
$this->getApplicationURI('resource/'));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
$resource->getName(),
|
||||
$this->getApplicationURI("resource/{$id}/"));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Logs'),
|
||||
$this->getApplicationURI("resource/{$id}/logs/"));
|
||||
} else if ($lease) {
|
||||
$id = $lease->getID();
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Leases'),
|
||||
$this->getApplicationURI('lease/'));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
$lease->getLeaseName(),
|
||||
$this->getApplicationURI("lease/{$id}/"));
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Logs'),
|
||||
$this->getApplicationURI("lease/{$id}/logs/"));
|
||||
}
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,53 @@ final class DrydockLogListController extends DrydockLogController {
|
|||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$querykey = $request->getURIData('queryKey');
|
||||
$engine = new DrydockLogSearchEngine();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
$type = $request->getURIData('type');
|
||||
switch ($type) {
|
||||
case 'blueprint':
|
||||
$blueprint = id(new DrydockBlueprintQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->executeOne();
|
||||
if (!$blueprint) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$engine->setBlueprint($blueprint);
|
||||
$this->setBlueprint($blueprint);
|
||||
break;
|
||||
case 'resource':
|
||||
$resource = id(new DrydockResourceQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->executeOne();
|
||||
if (!$resource) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$engine->setResource($resource);
|
||||
$this->setResource($resource);
|
||||
break;
|
||||
case 'lease':
|
||||
$lease = id(new DrydockLeaseQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->executeOne();
|
||||
if (!$lease) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$engine->setLease($lease);
|
||||
$this->setLease($lease);
|
||||
break;
|
||||
default:
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$query_key = $request->getURIData('queryKey');
|
||||
|
||||
$controller = id(new PhabricatorApplicationSearchController())
|
||||
->setQueryKey($querykey)
|
||||
->setSearchEngine(new DrydockLogSearchEngine())
|
||||
->setQueryKey($query_key)
|
||||
->setSearchEngine($engine)
|
||||
->setNavigation($this->buildSideNavView());
|
||||
|
||||
return $this->delegateToController($controller);
|
||||
|
|
|
@ -29,23 +29,15 @@ final class DrydockResourceViewController extends DrydockResourceController {
|
|||
$actions = $this->buildActionListView($resource);
|
||||
$properties = $this->buildPropertyListView($resource, $actions);
|
||||
|
||||
$resource_uri = 'resource/'.$resource->getID().'/';
|
||||
$resource_uri = $this->getApplicationURI($resource_uri);
|
||||
$id = $resource->getID();
|
||||
$resource_uri = $this->getApplicationURI("resource/{$id}/");
|
||||
|
||||
$pager = new PHUIPagerView();
|
||||
$pager->setURI(new PhutilURI($resource_uri), 'offset');
|
||||
$pager->setOffset($request->getInt('offset'));
|
||||
$log_query = id(new DrydockLogQuery())
|
||||
->withResourcePHIDs(array($resource->getPHID()));
|
||||
|
||||
$logs = id(new DrydockLogQuery())
|
||||
->setViewer($viewer)
|
||||
->withResourceIDs(array($resource->getID()))
|
||||
->executeWithOffsetPager($pager);
|
||||
|
||||
$log_table = id(new DrydockLogListView())
|
||||
->setUser($viewer)
|
||||
->setLogs($logs)
|
||||
->render();
|
||||
$log_table->appendChild($pager);
|
||||
$log_box = $this->buildLogBox(
|
||||
$log_query,
|
||||
$this->getApplicationURI("resource/{$id}/logs/query/all/"));
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Resource %d', $resource->getID()));
|
||||
|
@ -61,10 +53,6 @@ final class DrydockResourceViewController extends DrydockResourceController {
|
|||
|
||||
$lease_box = $this->buildLeaseBox($resource);
|
||||
|
||||
$log_box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Resource Logs'))
|
||||
->setTable($log_table);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
|
|
|
@ -2,112 +2,125 @@
|
|||
|
||||
final class DrydockLogQuery extends DrydockQuery {
|
||||
|
||||
private $resourceIDs;
|
||||
private $leaseIDs;
|
||||
private $blueprintPHIDs;
|
||||
private $resourcePHIDs;
|
||||
private $leasePHIDs;
|
||||
|
||||
public function withResourceIDs(array $ids) {
|
||||
$this->resourceIDs = $ids;
|
||||
public function withBlueprintPHIDs(array $phids) {
|
||||
$this->blueprintPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withLeaseIDs(array $ids) {
|
||||
$this->leaseIDs = $ids;
|
||||
public function withResourcePHIDs(array $phids) {
|
||||
$this->resourcePHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withLeasePHIDs(array $phids) {
|
||||
$this->leasePHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new DrydockLog();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new DrydockLog();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT log.* FROM %T log %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $logs) {
|
||||
$resource_ids = array_filter(mpull($logs, 'getResourceID'));
|
||||
if ($resource_ids) {
|
||||
protected function didFilterPage(array $logs) {
|
||||
$blueprint_phids = array_filter(mpull($logs, 'getBlueprintPHID'));
|
||||
if ($blueprint_phids) {
|
||||
$blueprints = id(new DrydockBlueprintQuery())
|
||||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($blueprint_phids)
|
||||
->execute();
|
||||
$blueprints = mpull($blueprints, null, 'getPHID');
|
||||
} else {
|
||||
$blueprints = array();
|
||||
}
|
||||
|
||||
foreach ($logs as $key => $log) {
|
||||
$blueprint = null;
|
||||
$blueprint_phid = $log->getBlueprintPHID();
|
||||
if ($blueprint_phid) {
|
||||
$blueprint = idx($blueprints, $blueprint_phid);
|
||||
}
|
||||
$log->attachBlueprint($blueprint);
|
||||
}
|
||||
|
||||
$resource_phids = array_filter(mpull($logs, 'getResourcePHID'));
|
||||
if ($resource_phids) {
|
||||
$resources = id(new DrydockResourceQuery())
|
||||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withIDs(array_unique($resource_ids))
|
||||
->withPHIDs($resource_phids)
|
||||
->execute();
|
||||
$resources = mpull($resources, null, 'getPHID');
|
||||
} else {
|
||||
$resources = array();
|
||||
}
|
||||
|
||||
foreach ($logs as $key => $log) {
|
||||
$resource = null;
|
||||
if ($log->getResourceID()) {
|
||||
$resource = idx($resources, $log->getResourceID());
|
||||
if (!$resource) {
|
||||
unset($logs[$key]);
|
||||
continue;
|
||||
}
|
||||
$resource_phid = $log->getResourcePHID();
|
||||
if ($resource_phid) {
|
||||
$resource = idx($resources, $resource_phid);
|
||||
}
|
||||
$log->attachResource($resource);
|
||||
}
|
||||
|
||||
$lease_ids = array_filter(mpull($logs, 'getLeaseID'));
|
||||
if ($lease_ids) {
|
||||
$lease_phids = array_filter(mpull($logs, 'getLeasePHID'));
|
||||
if ($lease_phids) {
|
||||
$leases = id(new DrydockLeaseQuery())
|
||||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withIDs(array_unique($lease_ids))
|
||||
->withPHIDs($lease_phids)
|
||||
->execute();
|
||||
$leases = mpull($leases, null, 'getPHID');
|
||||
} else {
|
||||
$leases = array();
|
||||
}
|
||||
|
||||
foreach ($logs as $key => $log) {
|
||||
$lease = null;
|
||||
if ($log->getLeaseID()) {
|
||||
$lease = idx($leases, $log->getLeaseID());
|
||||
if (!$lease) {
|
||||
unset($logs[$key]);
|
||||
continue;
|
||||
}
|
||||
$lease_phid = $log->getLeasePHID();
|
||||
if ($lease_phid) {
|
||||
$lease = idx($leases, $lease_phid);
|
||||
}
|
||||
$log->attachLease($lease);
|
||||
}
|
||||
|
||||
// These logs are meaningless and their policies aren't computable. They
|
||||
// shouldn't exist, but throw them away if they do.
|
||||
foreach ($logs as $key => $log) {
|
||||
if (!$log->getResource() && !$log->getLease()) {
|
||||
unset($logs[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->resourceIDs !== null) {
|
||||
if ($this->blueprintPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'resourceID IN (%Ld)',
|
||||
$this->resourceIDs);
|
||||
$conn,
|
||||
'blueprintPHID IN (%Ls)',
|
||||
$this->blueprintPHIDs);
|
||||
}
|
||||
|
||||
if ($this->leaseIDs !== null) {
|
||||
if ($this->resourcePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'leaseID IN (%Ld)',
|
||||
$this->leaseIDs);
|
||||
$conn,
|
||||
'resourcePHID IN (%Ls)',
|
||||
$this->resourcePHIDs);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
if ($this->leasePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'leasePHID IN (%Ls)',
|
||||
$this->leasePHIDs);
|
||||
}
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
return $where;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,43 @@
|
|||
|
||||
final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
|
||||
|
||||
private $blueprint;
|
||||
private $resource;
|
||||
private $lease;
|
||||
|
||||
public function setBlueprint(DrydockBlueprint $blueprint) {
|
||||
$this->blueprint = $blueprint;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBlueprint() {
|
||||
return $this->blueprint;
|
||||
}
|
||||
|
||||
public function setResource(DrydockResource $resource) {
|
||||
$this->resource = $resource;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getResource() {
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
public function setLease(DrydockLease $lease) {
|
||||
$this->lease = $lease;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLease() {
|
||||
return $this->lease;
|
||||
}
|
||||
|
||||
public function canUseInPanelContext() {
|
||||
// Prevent use on Dashboard panels since all log queries currently need a
|
||||
// parent object and these don't seem particularly useful in any case.
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getResultTypeDescription() {
|
||||
return pht('Drydock Logs');
|
||||
}
|
||||
|
@ -10,75 +47,59 @@ final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
|
|||
return 'PhabricatorDrydockApplication';
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromRequest(AphrontRequest $request) {
|
||||
$query = new PhabricatorSavedQuery();
|
||||
|
||||
$query->setParameter(
|
||||
'resourcePHIDs',
|
||||
$this->readListFromRequest($request, 'resources'));
|
||||
$query->setParameter(
|
||||
'leasePHIDs',
|
||||
$this->readListFromRequest($request, 'leases'));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
|
||||
$resource_phids = $saved->getParameter('resourcePHIDs', array());
|
||||
$lease_phids = $saved->getParameter('leasePHIDs', array());
|
||||
|
||||
// TODO: Change logs to use PHIDs instead of IDs.
|
||||
$resource_ids = array();
|
||||
$lease_ids = array();
|
||||
|
||||
if ($resource_phids) {
|
||||
$resource_ids = id(new DrydockResourceQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withPHIDs($resource_phids)
|
||||
->execute();
|
||||
$resource_ids = mpull($resource_ids, 'getID');
|
||||
}
|
||||
|
||||
if ($lease_phids) {
|
||||
$lease_ids = id(new DrydockLeaseQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withPHIDs($lease_phids)
|
||||
->execute();
|
||||
$lease_ids = mpull($lease_ids, 'getID');
|
||||
}
|
||||
|
||||
public function newQuery() {
|
||||
$query = new DrydockLogQuery();
|
||||
if ($resource_ids) {
|
||||
$query->withResourceIDs($resource_ids);
|
||||
|
||||
$blueprint = $this->getBlueprint();
|
||||
if ($blueprint) {
|
||||
$query->withBlueprintPHIDs(array($blueprint->getPHID()));
|
||||
}
|
||||
if ($lease_ids) {
|
||||
$query->withLeaseIDs($lease_ids);
|
||||
|
||||
$resource = $this->getResource();
|
||||
if ($resource) {
|
||||
$query->withResourcePHIDs(array($resource->getPHID()));
|
||||
}
|
||||
|
||||
$lease = $this->getLease();
|
||||
if ($lease) {
|
||||
$query->withLeasePHIDs(array($lease->getPHID()));
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function buildSearchForm(
|
||||
AphrontFormView $form,
|
||||
PhabricatorSavedQuery $saved) {
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
$form
|
||||
->appendControl(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
->setDatasource(new DrydockResourceDatasource())
|
||||
->setName('resources')
|
||||
->setLabel(pht('Resources'))
|
||||
->setValue($saved->getParameter('resourcePHIDs', array())))
|
||||
->appendControl(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
->setDatasource(new DrydockLeaseDatasource())
|
||||
->setName('leases')
|
||||
->setLabel(pht('Leases'))
|
||||
->setValue($saved->getParameter('leasePHIDs', array())));
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
return '/drydock/log/'.$path;
|
||||
$blueprint = $this->getBlueprint();
|
||||
if ($blueprint) {
|
||||
$id = $blueprint->getID();
|
||||
return "/drydock/blueprint/{$id}/logs/{$path}";
|
||||
}
|
||||
|
||||
$resource = $this->getResource();
|
||||
if ($resource) {
|
||||
$id = $resource->getID();
|
||||
return "/drydock/resource/{$id}/logs/{$path}";
|
||||
}
|
||||
|
||||
$lease = $this->getLease();
|
||||
if ($lease) {
|
||||
$id = $lease->getID();
|
||||
return "/drydock/lease/{$id}/logs/{$path}";
|
||||
}
|
||||
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Search engine has no blueprint, resource, or lease.'));
|
||||
}
|
||||
|
||||
protected function getBuiltinQueryNames() {
|
||||
|
|
|
@ -347,6 +347,9 @@ final class DrydockLease extends DrydockDAO
|
|||
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||
$need_update = false;
|
||||
|
||||
// TODO: This is just a placeholder to get some data in the table.
|
||||
$this->logEvent('activated');
|
||||
|
||||
$commands = id(new DrydockCommandQuery())
|
||||
->setViewer($viewer)
|
||||
->withTargetPHIDs(array($this->getPHID()))
|
||||
|
@ -371,6 +374,24 @@ final class DrydockLease extends DrydockDAO
|
|||
}
|
||||
}
|
||||
|
||||
public function logEvent($type, array $data = array()) {
|
||||
$log = id(new DrydockLog())
|
||||
->setEpoch(PhabricatorTime::getNow())
|
||||
->setType($type)
|
||||
->setData($data);
|
||||
|
||||
$log->setLeasePHID($this->getPHID());
|
||||
|
||||
$resource = $this->getResource();
|
||||
if ($resource) {
|
||||
$log->setResourcePHID($resource->getPHID());
|
||||
$log->setBlueprintPHID($resource->getBlueprintPHID());
|
||||
}
|
||||
|
||||
return $log->save();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -3,28 +3,38 @@
|
|||
final class DrydockLog extends DrydockDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $resourceID;
|
||||
protected $leaseID;
|
||||
protected $blueprintPHID;
|
||||
protected $resourcePHID;
|
||||
protected $leasePHID;
|
||||
protected $epoch;
|
||||
protected $message;
|
||||
protected $type;
|
||||
protected $data = array();
|
||||
|
||||
private $blueprint = self::ATTACHABLE;
|
||||
private $resource = self::ATTACHABLE;
|
||||
private $lease = self::ATTACHABLE;
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_TIMESTAMPS => false,
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'data' => self::SERIALIZATION_JSON,
|
||||
),
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'resourceID' => 'id?',
|
||||
'leaseID' => 'id?',
|
||||
'message' => 'text',
|
||||
'blueprintPHID' => 'phid?',
|
||||
'resourcePHID' => 'phid?',
|
||||
'leasePHID' => 'phid?',
|
||||
'type' => 'text64',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'resourceID' => array(
|
||||
'columns' => array('resourceID', 'epoch'),
|
||||
'key_blueprint' => array(
|
||||
'columns' => array('blueprintPHID', 'type'),
|
||||
),
|
||||
'leaseID' => array(
|
||||
'columns' => array('leaseID', 'epoch'),
|
||||
'key_resource' => array(
|
||||
'columns' => array('resourcePHID', 'type'),
|
||||
),
|
||||
'key_lease' => array(
|
||||
'columns' => array('leasePHID', 'type'),
|
||||
),
|
||||
'epoch' => array(
|
||||
'columns' => array('epoch'),
|
||||
|
@ -33,6 +43,15 @@ final class DrydockLog extends DrydockDAO
|
|||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function attachBlueprint(DrydockBlueprint $blueprint = null) {
|
||||
$this->blueprint = $blueprint;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBlueprint() {
|
||||
return $this->assertAttached($this->blueprint);
|
||||
}
|
||||
|
||||
public function attachResource(DrydockResource $resource = null) {
|
||||
$this->resource = $resource;
|
||||
return $this;
|
||||
|
@ -51,6 +70,22 @@ final class DrydockLog extends DrydockDAO
|
|||
return $this->assertAttached($this->lease);
|
||||
}
|
||||
|
||||
public function isComplete() {
|
||||
if ($this->getBlueprintPHID() && !$this->getBlueprint()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->getResourcePHID() && !$this->getResource()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->getLeasePHID() && !$this->getLease()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
@ -62,21 +97,19 @@ final class DrydockLog extends DrydockDAO
|
|||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
if ($this->getResource()) {
|
||||
return $this->getResource()->getPolicy($capability);
|
||||
}
|
||||
return $this->getLease()->getPolicy($capability);
|
||||
// NOTE: We let you see that logs exist no matter what, but don't actually
|
||||
// show you log content unless you can see all of the associated objects.
|
||||
return PhabricatorPolicies::getMostOpenPolicy();
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
if ($this->getResource()) {
|
||||
return $this->getResource()->hasAutomaticCapability($capability, $viewer);
|
||||
}
|
||||
return $this->getLease()->hasAutomaticCapability($capability, $viewer);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return pht('Logs inherit the policy of their resources.');
|
||||
return pht(
|
||||
'To view log details, you must be able to view the associated '.
|
||||
'blueprint, resource and lease.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,28 +18,45 @@ final class DrydockLogListView extends AphrontView {
|
|||
|
||||
$rows = array();
|
||||
foreach ($logs as $log) {
|
||||
$resource_uri = '/drydock/resource/'.$log->getResourceID().'/';
|
||||
$lease_uri = '/drydock/lease/'.$log->getLeaseID().'/';
|
||||
$blueprint_phid = $log->getBlueprintPHID();
|
||||
if ($blueprint_phid) {
|
||||
$blueprint = $viewer->renderHandle($blueprint_phid);
|
||||
} else {
|
||||
$blueprint = null;
|
||||
}
|
||||
|
||||
$resource_name = $log->getResourceID();
|
||||
if ($log->getResourceID() !== null) {
|
||||
$resource_name = $log->getResource()->getName();
|
||||
$resource_phid = $log->getResourcePHID();
|
||||
if ($resource_phid) {
|
||||
$resource = $viewer->renderHandle($resource_phid);
|
||||
} else {
|
||||
$resource = null;
|
||||
}
|
||||
|
||||
$lease_phid = $log->getLeasePHID();
|
||||
if ($lease_phid) {
|
||||
$lease = $viewer->renderHandle($lease_phid);
|
||||
} else {
|
||||
$lease = null;
|
||||
}
|
||||
|
||||
if ($log->isComplete()) {
|
||||
// TODO: This is a placeholder.
|
||||
$type = $log->getType();
|
||||
$data = print_r($log->getData(), true);
|
||||
} else {
|
||||
$type = phutil_tag('em', array(), pht('Restricted'));
|
||||
$data = phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht('You do not have permission to view this log event.'));
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $resource_uri,
|
||||
),
|
||||
$resource_name),
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $lease_uri,
|
||||
),
|
||||
$log->getLeaseID()),
|
||||
$log->getMessage(),
|
||||
$blueprint,
|
||||
$resource,
|
||||
$lease,
|
||||
$type,
|
||||
$data,
|
||||
phabricator_datetime($log->getEpoch(), $viewer),
|
||||
);
|
||||
}
|
||||
|
@ -48,20 +65,17 @@ final class DrydockLogListView extends AphrontView {
|
|||
$table->setDeviceReadyTable(true);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
pht('Blueprint'),
|
||||
pht('Resource'),
|
||||
pht('Lease'),
|
||||
pht('Message'),
|
||||
pht('Type'),
|
||||
pht('Data'),
|
||||
pht('Date'),
|
||||
));
|
||||
$table->setShortHeaders(
|
||||
array(
|
||||
pht('R'),
|
||||
pht('L'),
|
||||
pht('Message'),
|
||||
'',
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'wide',
|
||||
|
|
Loading…
Reference in a new issue